PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / trunk
Tutor LMS – eLearning and online course solution vtrunk
4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 4.0.2 4.0.1 4.0.0 3.9.15 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 month ago Admin.php 1 month ago Ajax.php 1 week ago Announcements.php 1 month ago Assets.php 3 weeks ago Backend_Page_Trait.php 1 year ago BaseController.php 1 year ago Config.php 1 month ago Container.php 1 year ago Course.php 5 days ago Course_Embed.php 3 years ago Course_Filter.php 1 week ago Course_List.php 1 month ago Course_Settings_Tabs.php 1 month ago Course_Widget.php 1 year ago Custom_Validation.php 1 month ago Dashboard.php 1 month ago Earnings.php 11 months ago FormHandler.php 1 month ago Frontend.php 1 month ago Gutenberg.php 1 year ago Icon.php 2 weeks ago Input.php 1 month ago Instructor.php 1 month ago Instructors_List.php 1 month ago Lesson.php 1 week ago Options_V2.php 1 month ago Permalink.php 1 month ago Post_types.php 1 month ago Private_Course_Access.php 1 month ago Q_And_A.php 1 month ago Question_Answers_List.php 1 year ago Quiz.php 2 weeks ago QuizBuilder.php 2 weeks ago Quiz_Attempts_List.php 1 month ago RestAPI.php 1 month ago Reviews.php 1 month ago Rewrite_Rules.php 2 years ago SampleCourse.php 1 month ago Shortcode.php 1 month ago Singleton.php 1 year ago Student.php 1 month ago Students_List.php 1 year ago Taxonomies.php 1 year ago Template.php 1 month ago Theme_Compatibility.php 3 years ago Tools.php 1 year ago Tools_V2.php 2 months ago Tutor.php 1 week ago TutorEDD.php 1 month ago Tutor_Base.php 2 years ago Tutor_Setup.php 1 month ago Upgrader.php 1 month ago User.php 3 weeks ago UserPreference.php 1 month ago Utils.php 1 week ago Video_Stream.php 1 week ago WhatsNew.php 1 month ago Withdraw.php 1 month ago Withdraw_Requests_List.php 1 year ago WooCommerce.php 2 weeks ago
Ajax.php
645 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 defined( 'ABSPATH' ) || exit;
14
15 use Tutor\GDPR\Controllers\LegalConsent;
16 use Tutor\Helpers\HttpHelper;
17 use Tutor\Models\LessonModel;
18 use Tutor\Traits\JsonResponse;
19
20 /**
21 * Ajax Class
22 *
23 * @since 1.0.0
24 */
25 class Ajax {
26 use JsonResponse;
27
28 const LOGIN_ERRORS_TRANSIENT_KEY = 'tutor_login_errors';
29
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_tutor_place_rating', array( $this, 'tutor_place_rating' ) );
44 add_action( 'wp_ajax_delete_tutor_review', array( $this, 'delete_tutor_review' ) );
45
46 add_action( 'wp_ajax_tutor_course_add_to_wishlist', array( $this, 'tutor_course_add_to_wishlist' ) );
47 add_action( 'wp_ajax_nopriv_tutor_course_add_to_wishlist', array( $this, 'tutor_course_add_to_wishlist' ) );
48
49 /**
50 * Ajax login
51 *
52 * @since v.1.6.3
53 */
54 add_action( 'tutor_action_tutor_user_login', array( $this, 'process_tutor_login' ) );
55
56 /**
57 * Announcement
58 *
59 * @since v.1.7.9
60 */
61 add_action( 'wp_ajax_tutor_announcement_create', array( $this, 'create_or_update_announcement' ) );
62 add_action( 'wp_ajax_tutor_announcement_delete', array( $this, 'delete_announcement' ) );
63
64 add_action( 'wp_ajax_tutor_youtube_video_duration', array( $this, 'ajax_youtube_video_duration' ) );
65 }
66 }
67
68
69
70 /**
71 * Update video information and data when necessary
72 *
73 * @since 1.0.0
74 *
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 do_action( 'tutor_lesson_completed_email_after', $post_id, $user_id );
116 }
117 exit();
118 }
119
120 /**
121 * Place rating
122 *
123 * @since 1.0.0
124 * @return void
125 */
126 public function tutor_place_rating() {
127 tutor_utils()->checking_nonce();
128
129 $user_id = get_current_user_id();
130 $course_id = Input::post( 'course_id' );
131 $rating = Input::post( 'tutor_rating_gen_input', 0, Input::TYPE_INT );
132 $review = Input::post( 'review', '', Input::TYPE_TEXTAREA );
133
134 $rating <= 0 ? $rating = 1 : 0;
135 $rating > 5 ? $rating = 5 : 0;
136
137 $this->add_or_update_review( $user_id, $course_id, $rating, $review );
138 }
139
140 /**
141 * Add/Update rating
142 *
143 * @param int $user_id the user id.
144 * @param int $course_id the course id.
145 * @param int $rating rating star number.
146 * @param string $review review description.
147 * @param int $review_id review id needed for api update.
148 *
149 * @return void|string
150 */
151 public function add_or_update_review( $user_id, $course_id, $rating, $review, $review_id = 0 ) {
152 global $wpdb;
153
154 $moderation = tutor_utils()->get_option( 'enable_course_review_moderation', false, true, true );
155 $user = get_userdata( $user_id );
156 $date = date( 'Y-m-d H:i:s', tutor_time() ); //phpcs:ignore
157
158 if ( ! tutor_is_rest() && ! tutor_utils()->has_enrolled_content_access( 'course', $course_id ) ) {
159 wp_send_json_error( array( 'message' => __( 'Access Denied', 'tutor' ) ) );
160 exit;
161 }
162
163 do_action( 'tutor_before_rating_placed' );
164
165 $is_edit = 0 === $review_id ? false : true;
166
167 if ( ! tutor_is_rest() ) {
168 $previous_rating_id = $wpdb->get_var(
169 $wpdb->prepare(
170 "SELECT comment_ID
171 from {$wpdb->comments}
172 WHERE comment_post_ID = %d AND
173 user_id = %d AND
174 comment_type = 'tutor_course_rating'
175 LIMIT 1;",
176 $course_id,
177 $user_id
178 )
179 );
180
181 if ( ! empty( $previous_rating_id ) ) {
182 $review_id = $previous_rating_id;
183 $is_edit = true;
184 }
185 }
186
187 if ( $is_edit ) {
188 $wpdb->update(
189 $wpdb->comments,
190 array(
191 'comment_content' => $review,
192 'comment_approved' => $moderation ? 'hold' : 'approved',
193 'comment_date' => $date,
194 'comment_date_gmt' => get_gmt_from_date( $date ),
195 ),
196 array( 'comment_ID' => $review_id )
197 );
198
199 $rating_info = $wpdb->get_row(
200 $wpdb->prepare(
201 "SELECT * FROM {$wpdb->commentmeta}
202 WHERE comment_id = %d
203 AND meta_key = 'tutor_rating'; ",
204 $review_id
205 )
206 );
207
208 if ( $rating_info ) {
209 $wpdb->update(
210 $wpdb->commentmeta,
211 array( 'meta_value' => $rating ),
212 array(
213 'comment_id' => $review_id,
214 'meta_key' => 'tutor_rating',
215 )
216 );
217 } else {
218 $wpdb->insert(
219 $wpdb->commentmeta,
220 array(
221 'comment_id' => $review_id,
222 'meta_key' => 'tutor_rating',
223 'meta_value' => $rating,
224 )
225 );
226 }
227 } else {
228 $data = array(
229 'comment_post_ID' => esc_sql( $course_id ),
230 'comment_approved' => $moderation ? 'hold' : 'approved',
231 'comment_type' => 'tutor_course_rating',
232 'comment_date' => $date,
233 'comment_date_gmt' => get_gmt_from_date( $date ),
234 'user_id' => $user_id,
235 'comment_author' => $user->user_login,
236 'comment_agent' => 'TutorLMSPlugin',
237 );
238 if ( $review ) {
239 $data['comment_content'] = $review;
240 }
241
242 $wpdb->insert( $wpdb->comments, $data );
243 $comment_id = (int) $wpdb->insert_id;
244 $review_id = $comment_id;
245
246 if ( $comment_id ) {
247 $wpdb->insert(
248 $wpdb->commentmeta,
249 array(
250 'comment_id' => $comment_id,
251 'meta_key' => 'tutor_rating',
252 'meta_value' => $rating,
253 )
254 );
255
256 do_action( 'tutor_after_rating_placed', $comment_id );
257 }
258 }
259
260 if ( ! tutor_is_rest() ) {
261 wp_send_json_success(
262 array(
263 'message' => __( 'Rating placed successfully!', 'tutor' ),
264 'review_id' => $review_id,
265 )
266 );
267 } else {
268 return $is_edit ? 'updated' : 'created';
269 }
270 }
271
272 /**
273 * Delete a review
274 *
275 * @since 1.0.0
276 * @since 2.6.2 added params user_id.
277 * @param int $user_id the user id.
278 * @return void|bool
279 */
280 public function delete_tutor_review( $user_id = 0 ) {
281 if ( ! tutor_is_rest() ) {
282 tutor_utils()->checking_nonce();
283 }
284
285 $review_id = Input::post( 'review_id' );
286
287 if ( ! tutor_utils()->can_user_manage( 'review', $review_id, tutils()->get_user_id( $user_id ) ) ) {
288 wp_send_json_error( array( 'message' => __( 'Permissioned Denied!', 'tutor' ) ) );
289 exit;
290 }
291
292 global $wpdb;
293 $wpdb->delete( $wpdb->commentmeta, array( 'comment_id' => $review_id ) );
294 $wpdb->delete( $wpdb->comments, array( 'comment_ID' => $review_id ) );
295
296 if ( tutor_is_rest() ) {
297 return true;
298 }
299
300 wp_send_json_success();
301 }
302
303 /**
304 * Add course in wishlist
305 *
306 * @since 1.0.0
307 * @return void|string
308 */
309 public function tutor_course_add_to_wishlist() {
310 tutor_utils()->checking_nonce();
311
312 $is_enabled_wishlist = tutor_utils()->get_option( 'enable_wishlist', true );
313 if ( ! $is_enabled_wishlist ) {
314 wp_send_json_error( array( 'message' => __( 'Wishlist option is disabled', 'tutor' ) ) );
315 }
316
317 // Redirect login since only logged in user can add courses to wishlist.
318 if ( ! is_user_logged_in() ) {
319 wp_send_json_error(
320 array(
321 'redirect_to' => wp_login_url( wp_get_referer() ),
322 )
323 );
324 }
325
326 $user_id = get_current_user_id();
327 $course_id = Input::post( 'course_id', 0, Input::TYPE_INT );
328
329 $result = $this->add_or_delete_wishlist( $user_id, $course_id );
330
331 if ( tutor_is_rest() ) {
332 return $result;
333 } elseif ( 'added' === $result ) {
334 wp_send_json_success(
335 array(
336 'status' => 'added',
337 'message' => __( 'Course added to wish list', 'tutor' ),
338 )
339 );
340 } else {
341 wp_send_json_success(
342 array(
343 'status' => 'removed',
344 'message' => __( 'Course removed from wish list', 'tutor' ),
345 )
346 );
347 }
348 }
349
350 /**
351 * Add or Delete wishlist by user_id and course_id
352 *
353 * @since 2.6.2
354 *
355 * @param int $user_id the user id.
356 * @param int $course_id the course_id to add to the wishlist.
357 *
358 * @return string
359 */
360 public function add_or_delete_wishlist( $user_id, $course_id ) {
361 global $wpdb;
362
363 $if_added_to_list = tutor_utils()->is_wishlisted( $course_id, $user_id );
364
365 $result = '';
366
367 if ( $if_added_to_list ) {
368 $wpdb->delete(
369 $wpdb->usermeta,
370 array(
371 'user_id' => $user_id,
372 'meta_key' => '_tutor_course_wishlist',
373 'meta_value' => $course_id,
374 )
375 );
376
377 $result = 'removed';
378 } else {
379 add_user_meta( $user_id, '_tutor_course_wishlist', $course_id );
380
381 $result = 'added';
382 }
383
384 return $result;
385 }
386
387 /**
388 * Process tutor login
389 *
390 * @since 1.6.3
391 * @since 2.1.3 Ajax removed, validation errors stores in session.
392 *
393 * @return void
394 */
395 public function process_tutor_login() {
396 $validation_error = new \WP_Error();
397
398 /**
399 * Separate nonce verification added to show nonce verification
400 * failed message in a proper way.
401 *
402 * @since 2.1.4
403 */
404 if ( ! tutor_utils()->is_nonce_verified( 'post' ) ) {
405 $validation_error->add( 401, __( 'Nonce verification failed', 'tutor' ) );
406 \set_transient( self::LOGIN_ERRORS_TRANSIENT_KEY, $validation_error->get_error_messages(), MINUTE_IN_SECONDS );
407 return;
408 }
409
410 /**
411 * No sanitization/wp_unslash needed for log & pwd since WordPress
412 * does itself
413 *
414 * @since 2.1.3
415 *
416 * @see https://developer.wordpress.org/reference/functions/wp_signon/
417 */
418 //phpcs:disable WordPress.Security.NonceVerification.Missing
419 $username = tutor_utils()->array_get( 'log', $_POST ); //phpcs:ignore
420 $password = tutor_utils()->array_get( 'pwd', $_POST ); //phpcs:ignore
421 $redirect_to = isset( $_POST['redirect_to'] ) ? esc_url_raw( wp_unslash( $_POST['redirect_to'] ) ) : '';
422 $remember = isset( $_POST['rememberme'] );
423 //phpcs:enable WordPress.Security.NonceVerification.Missing
424
425 try {
426 $creds = array(
427 'user_login' => trim( $username ),
428 'user_password' => $password,
429 'remember' => $remember,
430 );
431
432 $validation_error = apply_filters( 'tutor_process_login_errors', $validation_error, $creds['user_login'], $creds['user_password'] );
433 if ( $validation_error->get_error_code() ) {
434 $validation_error->add(
435 $validation_error->get_error_code(),
436 $validation_error->get_error_message()
437 );
438 }
439
440 if ( empty( $creds['user_login'] ) ) {
441 $validation_error->add(
442 400,
443 __( 'Username is required.', 'tutor' )
444 );
445 }
446
447 $validate_consent = LegalConsent::validate_consent( LegalConsent::DISPLAY_ON_LOGIN, $_POST );
448 if ( is_wp_error( $validate_consent ) ) {
449 $validation_error->add(
450 $validate_consent->get_error_code(),
451 $validate_consent->get_error_message(),
452 );
453 }
454
455 if ( $validation_error->has_errors() ) {
456 \set_transient( self::LOGIN_ERRORS_TRANSIENT_KEY, $validation_error->get_error_messages() );
457 return;
458 }
459
460 // On multi-site, ensure user exists on current site, if not add them before allowing login.
461 if ( is_multisite() ) {
462 $user_data = get_user_by( is_email( $creds['user_login'] ) ? 'email' : 'login', $creds['user_login'] );
463 if ( $user_data && ! is_user_member_of_blog( $user_data->ID, get_current_blog_id() ) ) {
464 add_user_to_blog( get_current_blog_id(), $user_data->ID, 'customer' );
465 }
466 }
467
468 // Perform the login.
469 $user = wp_signon( apply_filters( 'tutor_login_credentials', $creds ), is_ssl() );
470 if ( is_wp_error( $user ) ) {
471 // If no error exist then add WP login error, to prevent error duplication.
472 if ( ! $validation_error->has_errors() ) {
473 $validation_error->add( 400, $user->get_error_message() );
474 }
475 } else {
476 // @since 4.0.0 $validate _consent param added.
477 do_action( 'tutor_after_login_success', $user->ID, $validate_consent );
478
479 // Since 1.9.8 do enroll if guest attempt to enroll.
480 $course_enroll_attempt = Input::post( 'tutor_course_enroll_attempt' );
481 if ( ! empty( $course_enroll_attempt ) && is_a( $user, 'WP_User' ) ) {
482 do_action( 'tutor_do_enroll_after_login_if_attempt', $course_enroll_attempt, $user->ID );
483 }
484 wp_safe_redirect( $redirect_to );
485 exit();
486 }
487 } catch ( \Exception $e ) {
488 do_action( 'tutor_login_failed' );
489 $validation_error->add( 400, $e->getMessage() );
490 } finally {
491 // Store errors in transient data.
492 \set_transient( self::LOGIN_ERRORS_TRANSIENT_KEY, $validation_error->get_error_messages(), MINUTE_IN_SECONDS );
493 }
494 }
495
496 /**
497 * Create/Update announcement
498 *
499 * @since 1.7.9
500 *
501 * @return void
502 */
503 public function create_or_update_announcement() {
504 tutor_utils()->checking_nonce();
505
506 $error = array();
507 $course_id = Input::post( 'tutor_announcement_course' );
508 $announcement_title = Input::post( 'tutor_announcement_title' );
509 $announcement_summary = Input::post( 'tutor_announcement_summary', '', Input::TYPE_TEXTAREA );
510
511 // Check if user can manage this announcement.
512 if ( ! tutor_utils()->can_user_manage( 'course', $course_id ) ) {
513 wp_send_json_error( array( 'message' => __( 'Access Denied', 'tutor' ) ) );
514 }
515
516 // Set data and sanitize it.
517 $form_data = array(
518 'post_type' => 'tutor_announcements',
519 'post_title' => $announcement_title,
520 'post_content' => $announcement_summary,
521 'post_parent' => $course_id,
522 'post_status' => 'publish',
523 );
524
525 if ( Input::has( 'announcement_id' ) ) {
526 $form_data['ID'] = Input::post( 'announcement_id' );
527 }
528
529 if ( ! empty( $form_data['ID'] ) ) {
530 if ( ! tutor_utils()->can_user_manage( 'announcement', $form_data['ID'] ) ) {
531 wp_send_json_error( array( 'message' => tutor_utils()->error_message() ) );
532 }
533 }
534
535 // Validation message set.
536 if ( empty( $form_data['post_parent'] ) ) {
537 $error['post_parent'] = __( 'Course name required', 'tutor' );
538
539 }
540
541 if ( empty( $form_data['post_title'] ) ) {
542 $error['post_title'] = __( 'Announcement title required', 'tutor' );
543 }
544
545 if ( empty( $form_data['post_content'] ) ) {
546 $error['post_content'] = __( 'Announcement summary required', 'tutor' );
547
548 }
549
550 if ( empty( $form_data['post_content'] ) ) {
551 $error['post_content'] = __( 'Announcement summary required', 'tutor' );
552
553 }
554
555 // If validation fails.
556 if ( count( $error ) > 0 ) {
557 wp_send_json_error(
558 array(
559 'message' => __( 'All fields required!', 'tutor' ),
560 'fields' => $error,
561 )
562 );
563 }
564
565 // Insert or update post.
566 $post_id = wp_insert_post( $form_data );
567 if ( $post_id > 0 ) {
568 $announcement = get_post( $post_id );
569 $action_type = Input::post( 'action_type' );
570
571 do_action( 'tutor_announcements/after/save', $post_id, $announcement, $action_type );
572
573 $resp_message = 'create' === $action_type ? __( 'Announcement created successfully', 'tutor' ) : __( 'Announcement updated successfully', 'tutor' );
574 wp_send_json_success( array( 'message' => $resp_message ) );
575 }
576
577 wp_send_json_error( array( 'message' => __( 'Something Went Wrong!', 'tutor' ) ) );
578 }
579
580 /**
581 * Delete announcement
582 *
583 * @since 1.7.9
584 *
585 * @return void
586 */
587 public function delete_announcement() {
588 tutor_utils()->checking_nonce();
589
590 $announcement_id = Input::post( 'announcement_id' );
591
592 if ( ! tutor_utils()->can_user_manage( 'announcement', $announcement_id ) ) {
593 wp_send_json_error( array( 'message' => __( 'Access Denied', 'tutor' ) ) );
594 }
595
596 $delete = wp_delete_post( $announcement_id );
597 if ( $delete ) {
598 wp_send_json_success( array( 'message' => __( 'Announcement deleted successfully', 'tutor' ) ) );
599 }
600
601 wp_send_json_error( array( 'message' => __( 'Announcement delete failed', 'tutor' ) ) );
602 }
603
604 /**
605 * Get youtube video duration.
606 *
607 * @since 3.0.0
608 *
609 * @return void
610 */
611 public function ajax_youtube_video_duration() {
612 tutor_utils()->check_nonce();
613
614 $video_id = Input::post( 'video_id' );
615 if ( empty( $video_id ) ) {
616 $this->json_response( __( 'Video ID is required', 'tutor' ), null, HttpHelper::STATUS_BAD_REQUEST );
617 }
618
619 tutor_utils()->check_current_user_capability( 'edit_tutor_courses' );
620
621 $api_key = tutor_utils()->get_option( 'lesson_video_duration_youtube_api_key', '' );
622 $url = "https://www.googleapis.com/youtube/v3/videos?id=$video_id&part=contentDetails&key=$api_key";
623
624 $request = HttpHelper::get( $url );
625 if ( HttpHelper::STATUS_OK === $request->get_status_code() ) {
626 $response = $request->get_json();
627 if ( isset( $response->items[0]->contentDetails->duration ) ) {
628 $duration = $response->items[0]->contentDetails->duration;
629 $this->json_response(
630 __( 'Fetched duration successfully', 'tutor' ),
631 array(
632 'duration' => $duration,
633 )
634 );
635 }
636 }
637
638 $this->json_response(
639 __( 'Failed to fetch duration', 'tutor' ),
640 null,
641 HttpHelper::STATUS_BAD_REQUEST
642 );
643 }
644 }
645