PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 3.2.3
Tutor LMS – eLearning and online course solution v3.2.3
3.9.14 3.9.13 3.9.12 3.9.11 trunk 1.0.0 1.0.0-alpha 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.2.0 1.2.1 1.2.11 1.2.12 1.2.13 1.2.20 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.1 1.8.10 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.15 1.9.16 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.10 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.1.1 2.1.10 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.3.0 2.4.0 2.5.0 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 3.0.0 3.0.1 3.0.2 3.1.0 3.2.0 3.2.1 3.2.2 3.2.3 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.7.0 3.7.1 3.7.2 3.7.3 3.7.4 3.8.0 3.8.1 3.8.2 3.8.3 3.9.0 3.9.1 3.9.10 3.9.2 3.9.3 3.9.4 3.9.5 3.9.6 3.9.7 3.9.8 3.9.9
tutor / classes / Ajax.php
tutor / classes Last commit date
Addons.php 1 year ago Admin.php 1 year ago Ajax.php 1 year ago Announcements.php 1 year ago Assets.php 1 year ago Backend_Page_Trait.php 1 year ago BaseController.php 1 year ago Course.php 1 year ago Course_Embed.php 3 years ago Course_Filter.php 1 year ago Course_List.php 1 year ago Course_Settings_Tabs.php 1 year ago Course_Widget.php 1 year ago Custom_Validation.php 3 years ago Dashboard.php 1 year ago Earnings.php 1 year ago FormHandler.php 2 years ago Frontend.php 1 year ago Gutenberg.php 1 year ago Input.php 1 year ago Instructor.php 1 year ago Instructors_List.php 1 year ago Lesson.php 1 year ago Options_V2.php 1 year ago Permalink.php 2 years ago Post_types.php 1 year ago Private_Course_Access.php 1 year ago Q_And_A.php 1 year ago Question_Answers_List.php 3 years ago Quiz.php 1 year ago QuizBuilder.php 1 year ago Quiz_Attempts_List.php 1 year ago RestAPI.php 2 years ago Reviews.php 3 years ago Rewrite_Rules.php 2 years ago Shortcode.php 1 year ago Singleton.php 1 year ago Student.php 1 year ago Students_List.php 3 years ago Taxonomies.php 3 years ago Template.php 1 year ago Theme_Compatibility.php 3 years ago Tools.php 1 year ago Tools_V2.php 1 year ago Tutor.php 1 year ago TutorEDD.php 1 year ago Tutor_Base.php 2 years ago Tutor_Setup.php 1 year ago Upgrader.php 1 year ago User.php 1 year ago Utils.php 1 year ago Video_Stream.php 3 years ago WhatsNew.php 2 years ago Withdraw.php 1 year ago Withdraw_Requests_List.php 1 year ago WooCommerce.php 1 year ago
Ajax.php
634 lines
1 <?php
2 /**
3 * Handle Ajax Request
4 *
5 * @package Tutor
6 * @author Themeum <support@themeum.com>
7 * @link https://themeum.com
8 * @since 1.0.0
9 */
10
11 namespace TUTOR;
12
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17 use Tutor\Helpers\HttpHelper;
18 use Tutor\Models\LessonModel;
19 use Tutor\Traits\JsonResponse;
20
21 /**
22 * Ajax Class
23 *
24 * @since 1.0.0
25 */
26 class Ajax {
27 use JsonResponse;
28
29 const LOGIN_ERRORS_TRANSIENT_KEY = 'tutor_login_errors';
30 /**
31 * Constructor
32 *
33 * @since 1.0.0
34 * @since 2.6.2 added allow_hooks param.
35 *
36 * @param bool $allow_hooks default value true.
37 *
38 * @return void
39 */
40 public function __construct( $allow_hooks = true ) {
41 if ( $allow_hooks ) {
42 add_action( 'wp_ajax_sync_video_playback', array( $this, 'sync_video_playback' ) );
43 add_action( 'wp_ajax_nopriv_sync_video_playback', array( $this, 'sync_video_playback_noprev' ) );
44 add_action( 'wp_ajax_tutor_place_rating', array( $this, 'tutor_place_rating' ) );
45 add_action( 'wp_ajax_delete_tutor_review', array( $this, 'delete_tutor_review' ) );
46
47 add_action( 'wp_ajax_tutor_course_add_to_wishlist', array( $this, 'tutor_course_add_to_wishlist' ) );
48 add_action( 'wp_ajax_nopriv_tutor_course_add_to_wishlist', array( $this, 'tutor_course_add_to_wishlist' ) );
49
50 /**
51 * Ajax login
52 *
53 * @since v.1.6.3
54 */
55 add_action( 'tutor_action_tutor_user_login', array( $this, 'process_tutor_login' ) );
56
57 /**
58 * Announcement
59 *
60 * @since v.1.7.9
61 */
62 add_action( 'wp_ajax_tutor_announcement_create', array( $this, 'create_or_update_annoucement' ) );
63 add_action( 'wp_ajax_tutor_announcement_delete', array( $this, 'delete_annoucement' ) );
64
65 add_action( 'wp_ajax_tutor_youtube_video_duration', array( $this, 'ajax_youtube_video_duration' ) );
66 }
67 }
68
69
70
71 /**
72 * Update video information and data when necessary
73 *
74 * @since 1.0.0
75 * @return void
76 */
77 public function sync_video_playback() {
78 tutor_utils()->checking_nonce();
79
80 $user_id = get_current_user_id();
81 $post_id = Input::post( 'post_id', 0, Input::TYPE_INT );
82 $duration = Input::post( 'duration' );
83 $current_time = Input::post( 'currentTime' );
84
85 if ( ! tutor_utils()->has_enrolled_content_access( 'lesson', $post_id ) ) {
86 wp_send_json_error( array( 'message' => __( 'Access Denied', 'tutor' ) ) );
87 exit;
88 }
89
90 /**
91 * Update posts attached video
92 */
93 $video = tutor_utils()->get_video( $post_id );
94
95 if ( $duration ) {
96 $video['duration_sec'] = $duration; // Duration in sec.
97 $video['playtime'] = tutor_utils()->playtime_string( $duration );
98 $video['runtime'] = tutor_utils()->playtime_array( $duration );
99 }
100 tutor_utils()->update_video( $post_id, $video );
101
102 /**
103 * Sync Lesson Reading Info by Users
104 */
105
106 $best_watch_time = tutor_utils()->get_lesson_reading_info( $post_id, $user_id, 'video_best_watched_time' );
107 if ( $best_watch_time < $current_time ) {
108 LessonModel::update_lesson_reading_info( $post_id, $user_id, 'video_best_watched_time', $current_time );
109 }
110
111 if ( Input::post( 'is_ended', false, Input::TYPE_BOOL ) ) {
112 LessonModel::mark_lesson_complete( $post_id );
113 LessonModel::update_lesson_reading_info( $post_id, $user_id, 'video_best_watched_time', 0 );
114 }
115 exit();
116 }
117
118 /**
119 * Video playback callback for noprev
120 *
121 * @since 1.0.0
122 * @return void
123 */
124 public function sync_video_playback_noprev() {
125 }
126
127 /**
128 * Place rating
129 *
130 * @since 1.0.0
131 * @return void
132 */
133 public function tutor_place_rating() {
134 tutor_utils()->checking_nonce();
135
136 $user_id = get_current_user_id();
137 $course_id = Input::post( 'course_id' );
138 $rating = Input::post( 'tutor_rating_gen_input', 0, Input::TYPE_INT );
139 $review = Input::post( 'review', '', Input::TYPE_TEXTAREA );
140
141 $rating <= 0 ? $rating = 1 : 0;
142 $rating > 5 ? $rating = 5 : 0;
143
144 $this->add_or_update_review( $user_id, $course_id, $rating, $review );
145 }
146
147 /**
148 * Add/Update rating
149 *
150 * @param int $user_id the user id.
151 * @param int $course_id the course id.
152 * @param int $rating rating star number.
153 * @param string $review review description.
154 * @param int $review_id review id needed for api update.
155 *
156 * @return void|string
157 */
158 public function add_or_update_review( $user_id, $course_id, $rating, $review, $review_id = 0 ) {
159 global $wpdb;
160
161 $moderation = tutor_utils()->get_option( 'enable_course_review_moderation', false, true, true );
162 $user = get_userdata( $user_id );
163 $date = date( 'Y-m-d H:i:s', tutor_time() ); //phpcs:ignore
164
165 if ( ! tutor_is_rest() && ! tutor_utils()->has_enrolled_content_access( 'course', $course_id ) ) {
166 wp_send_json_error( array( 'message' => __( 'Access Denied', 'tutor' ) ) );
167 exit;
168 }
169
170 do_action( 'tutor_before_rating_placed' );
171
172 $is_edit = 0 === $review_id ? false : true;
173
174 if ( ! tutor_is_rest() ) {
175 $previous_rating_id = $wpdb->get_var(
176 $wpdb->prepare(
177 "SELECT comment_ID
178 from {$wpdb->comments}
179 WHERE comment_post_ID = %d AND
180 user_id = %d AND
181 comment_type = 'tutor_course_rating'
182 LIMIT 1;",
183 $course_id,
184 $user_id
185 )
186 );
187
188 if ( ! empty( $previous_rating_id ) ) {
189 $review_id = $previous_rating_id;
190 $is_edit = true;
191 }
192 }
193
194 if ( $is_edit ) {
195 $wpdb->update(
196 $wpdb->comments,
197 array(
198 'comment_content' => $review,
199 'comment_approved' => $moderation ? 'hold' : 'approved',
200 'comment_date' => $date,
201 'comment_date_gmt' => get_gmt_from_date( $date ),
202 ),
203 array( 'comment_ID' => $review_id )
204 );
205
206 $rating_info = $wpdb->get_row(
207 $wpdb->prepare(
208 "SELECT * FROM {$wpdb->commentmeta}
209 WHERE comment_id = %d
210 AND meta_key = 'tutor_rating'; ",
211 $review_id
212 )
213 );
214
215 if ( $rating_info ) {
216 $wpdb->update(
217 $wpdb->commentmeta,
218 array( 'meta_value' => $rating ),
219 array(
220 'comment_id' => $review_id,
221 'meta_key' => 'tutor_rating',
222 )
223 );
224 } else {
225 $wpdb->insert(
226 $wpdb->commentmeta,
227 array(
228 'comment_id' => $review_id,
229 'meta_key' => 'tutor_rating',
230 'meta_value' => $rating,
231 )
232 );
233 }
234 } else {
235 $data = array(
236 'comment_post_ID' => esc_sql( $course_id ),
237 'comment_approved' => $moderation ? 'hold' : 'approved',
238 'comment_type' => 'tutor_course_rating',
239 'comment_date' => $date,
240 'comment_date_gmt' => get_gmt_from_date( $date ),
241 'user_id' => $user_id,
242 'comment_author' => $user->user_login,
243 'comment_agent' => 'TutorLMSPlugin',
244 );
245 if ( $review ) {
246 $data['comment_content'] = $review;
247 }
248
249 $wpdb->insert( $wpdb->comments, $data );
250 $comment_id = (int) $wpdb->insert_id;
251 $review_id = $comment_id;
252
253 if ( $comment_id ) {
254 $wpdb->insert(
255 $wpdb->commentmeta,
256 array(
257 'comment_id' => $comment_id,
258 'meta_key' => 'tutor_rating',
259 'meta_value' => $rating,
260 )
261 );
262
263 do_action( 'tutor_after_rating_placed', $comment_id );
264 }
265 }
266
267 if ( ! tutor_is_rest() ) {
268 wp_send_json_success(
269 array(
270 'message' => __( 'Rating placed successfully!', 'tutor' ),
271 'review_id' => $review_id,
272 )
273 );
274 } else {
275 return $is_edit ? 'updated' : 'created';
276 }
277 }
278
279 /**
280 * Delete a review
281 *
282 * @since 1.0.0
283 * @since 2.6.2 added params user_id.
284 * @param int $user_id the user id.
285 * @return void|bool
286 */
287 public function delete_tutor_review( $user_id = 0 ) {
288 if ( ! tutor_is_rest() ) {
289 tutor_utils()->checking_nonce();
290 }
291
292 $review_id = Input::post( 'review_id' );
293
294 if ( ! tutor_utils()->can_user_manage( 'review', $review_id, tutils()->get_user_id( $user_id ) ) ) {
295 wp_send_json_error( array( 'message' => __( 'Permissioned Denied!', 'tutor' ) ) );
296 exit;
297 }
298
299 global $wpdb;
300 $wpdb->delete( $wpdb->commentmeta, array( 'comment_id' => $review_id ) );
301 $wpdb->delete( $wpdb->comments, array( 'comment_ID' => $review_id ) );
302
303 if ( tutor_is_rest() ) {
304 return true;
305 }
306
307 wp_send_json_success();
308 }
309
310 /**
311 * Add course in wishlist
312 *
313 * @since 1.0.0
314 * @return void|string
315 */
316 public function tutor_course_add_to_wishlist() {
317 tutor_utils()->checking_nonce();
318
319 // Redirect login since only logged in user can add courses to wishlist.
320 if ( ! is_user_logged_in() ) {
321 wp_send_json_error(
322 array(
323 'redirect_to' => wp_login_url( wp_get_referer() ),
324 )
325 );
326 }
327
328 $user_id = get_current_user_id();
329 $course_id = Input::post( 'course_id', 0, Input::TYPE_INT );
330
331 $result = $this->add_or_delete_wishlist( $user_id, $course_id );
332
333 if ( tutor_is_rest() ) {
334 return $result;
335 } elseif ( 'added' === $result ) {
336 wp_send_json_success(
337 array(
338 'status' => 'added',
339 'message' => __( 'Course added to wish list', 'tutor' ),
340 )
341 );
342 } else {
343 wp_send_json_success(
344 array(
345 'status' => 'removed',
346 'message' => __( 'Course removed from wish list', 'tutor' ),
347 )
348 );
349 }
350 }
351
352 /**
353 * Add or Delete wishlist by user_id and course_id
354 *
355 * @since 2.6.2
356 *
357 * @param int $user_id the user id.
358 * @param int $course_id the course_id to add to the wishlist.
359 *
360 * @return string
361 */
362 public function add_or_delete_wishlist( $user_id, $course_id ) {
363 global $wpdb;
364
365 $if_added_to_list = tutor_utils()->is_wishlisted( $course_id, $user_id );
366
367 $result = '';
368
369 if ( $if_added_to_list ) {
370 $wpdb->delete(
371 $wpdb->usermeta,
372 array(
373 'user_id' => $user_id,
374 'meta_key' => '_tutor_course_wishlist',
375 'meta_value' => $course_id,
376 )
377 );
378
379 $result = 'removed';
380 } else {
381 add_user_meta( $user_id, '_tutor_course_wishlist', $course_id );
382
383 $result = 'added';
384 }
385
386 return $result;
387 }
388
389 /**
390 * Process tutor login
391 *
392 * @since 1.6.3
393 *
394 * @since 2.1.3 Ajax removed, validation errors
395 * stores in session.
396 *
397 * @return void
398 */
399 public function process_tutor_login() {
400 $validation_error = new \WP_Error();
401
402 /**
403 * Separate nonce verification added to show nonce verification
404 * failed message in a proper way.
405 *
406 * @since 2.1.4
407 */
408 if ( ! wp_verify_nonce( $_POST[ tutor()->nonce ], tutor()->nonce_action ) ) { //phpcs:ignore
409 $validation_error->add( 401, __( 'Nonce verification failed', 'tutor' ) );
410 \set_transient( self::LOGIN_ERRORS_TRANSIENT_KEY, $validation_error->get_error_messages() );
411 return;
412 }
413 //phpcs:disable WordPress.Security.NonceVerification.Missing
414
415 /**
416 * No sanitization/wp_unslash needed for log & pwd since WordPress
417 * does itself
418 *
419 * @since 2.1.3
420 *
421 * @see https://developer.wordpress.org/reference/functions/wp_signon/
422 */
423 $username = tutor_utils()->array_get( 'log', $_POST ); //phpcs:ignore
424 $password = tutor_utils()->array_get( 'pwd', $_POST ); //phpcs:ignore
425 $redirect_to = isset( $_POST['redirect_to'] ) ? esc_url_raw( wp_unslash( $_POST['redirect_to'] ) ) : '';
426 $remember = isset( $_POST['rememberme'] );
427
428 try {
429 $creds = array(
430 'user_login' => trim( $username ),
431 'user_password' => $password,
432 'remember' => $remember,
433 );
434
435 $validation_error = apply_filters( 'tutor_process_login_errors', $validation_error, $creds['user_login'], $creds['user_password'] );
436
437 if ( $validation_error->get_error_code() ) {
438 $validation_error->add(
439 $validation_error->get_error_code(),
440 $validation_error->get_error_message()
441 );
442 }
443
444 if ( empty( $creds['user_login'] ) ) {
445 $validation_error->add(
446 400,
447 __( 'Username is required.', 'tutor' )
448 );
449 }
450
451 // On multi-site, ensure user exists on current site, if not add them before allowing login.
452 if ( is_multisite() ) {
453 $user_data = get_user_by( is_email( $creds['user_login'] ) ? 'email' : 'login', $creds['user_login'] );
454
455 if ( $user_data && ! is_user_member_of_blog( $user_data->ID, get_current_blog_id() ) ) {
456 add_user_to_blog( get_current_blog_id(), $user_data->ID, 'customer' );
457 }
458 }
459
460 // Perform the login.
461 $user = wp_signon( apply_filters( 'tutor_login_credentials', $creds ), is_ssl() );
462
463 if ( is_wp_error( $user ) ) {
464 // If no error exist then add WP login error, to prevent error duplication.
465 if ( ! $validation_error->has_errors() ) {
466 $validation_error->add( 400, $user->get_error_message() );
467 }
468 } else {
469 do_action( 'tutor_after_login_success', $user->ID );
470 // Since 1.9.8 do enroll if guest attempt to enroll.
471 $course_enroll_attempt = Input::post( 'tutor_course_enroll_attempt' );
472 if ( ! empty( $course_enroll_attempt ) && is_a( $user, 'WP_User' ) ) {
473 do_action( 'tutor_do_enroll_after_login_if_attempt', $course_enroll_attempt, $user->ID );
474 }
475 wp_safe_redirect( $redirect_to );
476 exit();
477 }
478 } catch ( \Exception $e ) {
479 do_action( 'tutor_login_failed' );
480 $validation_error->add( 400, $e->getMessage() );
481 } finally {
482 // Store errors in transient data.
483 \set_transient( self::LOGIN_ERRORS_TRANSIENT_KEY, $validation_error->get_error_messages() );
484 }
485 }
486
487 /**
488 * Create/Update announcement
489 *
490 * @since 1.7.9
491 * @return void
492 */
493 public function create_or_update_annoucement() {
494 tutor_utils()->checking_nonce();
495
496 $error = array();
497 $course_id = Input::post( 'tutor_announcement_course' );
498 $announcement_title = Input::post( 'tutor_announcement_title' );
499 $announcement_summary = Input::post( 'tutor_announcement_summary', '', Input::TYPE_TEXTAREA );
500
501 // Check if user can manage this announcment.
502 if ( ! tutor_utils()->can_user_manage( 'course', $course_id ) ) {
503 wp_send_json_error( array( 'message' => __( 'Access Denied', 'tutor' ) ) );
504 }
505
506 // Set data and sanitize it.
507 $form_data = array(
508 'post_type' => 'tutor_announcements',
509 'post_title' => $announcement_title,
510 'post_content' => $announcement_summary,
511 'post_parent' => $course_id,
512 'post_status' => 'publish',
513 );
514
515 if ( Input::has( 'announcement_id' ) ) {
516 $form_data['ID'] = Input::post( 'announcement_id' );
517 }
518
519 if ( ! empty( $form_data['ID'] ) ) {
520 if ( ! tutor_utils()->can_user_manage( 'announcement', $form_data['ID'] ) ) {
521 wp_send_json_error( array( 'message' => tutor_utils()->error_message() ) );
522 }
523 }
524
525 // Validation message set.
526 if ( empty( $form_data['post_parent'] ) ) {
527 $error['post_parent'] = __( 'Course name required', 'tutor' );
528
529 }
530
531 if ( empty( $form_data['post_title'] ) ) {
532 $error['post_title'] = __( 'Announcement title required', 'tutor' );
533 }
534
535 if ( empty( $form_data['post_content'] ) ) {
536 $error['post_content'] = __( 'Announcement summary required', 'tutor' );
537
538 }
539
540 if ( empty( $form_data['post_content'] ) ) {
541 $error['post_content'] = __( 'Announcement summary required', 'tutor' );
542
543 }
544
545 // If validation fails.
546 if ( count( $error ) > 0 ) {
547 wp_send_json_error(
548 array(
549 'message' => __( 'All fields required!', 'tutor' ),
550 'fields' => $error,
551 )
552 );
553 }
554
555 // Insert or update post.
556 $post_id = wp_insert_post( $form_data );
557 if ( $post_id > 0 ) {
558 $announcement = get_post( $post_id );
559 $action_type = Input::post( 'action_type' );
560
561 do_action( 'tutor_announcements/after/save', $post_id, $announcement, $action_type );
562
563 $resp_message = 'create' === $action_type ? __( 'Announcement created successfully', 'tutor' ) : __( 'Announcement updated successfully', 'tutor' );
564 wp_send_json_success( array( 'message' => $resp_message ) );
565 }
566
567 wp_send_json_error( array( 'message' => __( 'Something Went Wrong!', 'tutor' ) ) );
568 }
569
570 /**
571 * Delete announcement
572 *
573 * @since 1.7.9
574 * @return void
575 */
576 public function delete_annoucement() {
577 tutor_utils()->checking_nonce();
578
579 $announcement_id = Input::post( 'announcement_id' );
580
581 if ( ! tutor_utils()->can_user_manage( 'announcement', $announcement_id ) ) {
582 wp_send_json_error( array( 'message' => __( 'Access Denied', 'tutor' ) ) );
583 }
584
585 $delete = wp_delete_post( $announcement_id );
586 if ( $delete ) {
587 wp_send_json_success( array( 'message' => __( 'Announcement deleted successfully', 'tutor' ) ) );
588 }
589
590 wp_send_json_error( array( 'message' => __( 'Announcement delete failed', 'tutor' ) ) );
591 }
592
593 /**
594 * Get youtube video duration.
595 *
596 * @since 3.0.0
597 *
598 * @return void
599 */
600 public function ajax_youtube_video_duration() {
601 tutor_utils()->check_nonce();
602
603 $video_id = Input::post( 'video_id' );
604 if ( empty( $video_id ) ) {
605 $this->json_response( __( 'Video ID is required', 'tutor' ), null, HttpHelper::STATUS_BAD_REQUEST );
606 }
607
608 tutor_utils()->check_current_user_capability( 'edit_tutor_course' );
609
610 $api_key = tutor_utils()->get_option( 'lesson_video_duration_youtube_api_key', '' );
611 $url = "https://www.googleapis.com/youtube/v3/videos?id=$video_id&part=contentDetails&key=$api_key";
612
613 $request = HttpHelper::get( $url );
614 if ( HttpHelper::STATUS_OK === $request->get_status_code() ) {
615 $response = $request->get_json();
616 if ( isset( $response->items[0]->contentDetails->duration ) ) {
617 $duration = $response->items[0]->contentDetails->duration;
618 $this->json_response(
619 __( 'Fetched duration successfully', 'tutor' ),
620 array(
621 'duration' => $duration,
622 )
623 );
624 }
625 }
626
627 $this->json_response(
628 __( 'Failed to fetch duration', 'tutor' ),
629 null,
630 HttpHelper::STATUS_BAD_REQUEST
631 );
632 }
633 }
634