PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 2.7.7
Tutor LMS – eLearning and online course solution v2.7.7
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 2 years ago Admin.php 2 years ago Ajax.php 1 year ago Announcements.php 1 year ago Assets.php 2 years ago Backend_Page_Trait.php 3 years 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 3 years ago Course_Widget.php 3 years ago Custom_Validation.php 3 years ago Dashboard.php 3 years ago FormHandler.php 2 years ago Frontend.php 2 years ago Gutenberg.php 3 years ago Input.php 3 years 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 2 years ago Private_Course_Access.php 3 years ago Q_And_A.php 1 year ago Question_Answers_List.php 3 years ago Quiz.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 Student.php 2 years ago Students_List.php 3 years ago Taxonomies.php 3 years ago Template.php 2 years ago Theme_Compatibility.php 3 years ago Tools.php 3 years ago Tools_V2.php 2 years ago Tutor.php 2 years ago TutorEDD.php 2 years ago Tutor_Base.php 2 years ago Tutor_Setup.php 2 years ago Upgrader.php 2 years ago User.php 2 years ago Utils.php 1 year ago Video_Stream.php 3 years ago WhatsNew.php 2 years ago Withdraw.php 2 years ago Withdraw_Requests_List.php 3 years ago WooCommerce.php 1 year ago
Ajax.php
758 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\Models\LessonModel;
18
19 /**
20 * Ajax Class
21 *
22 * @since 1.0.0
23 */
24 class Ajax {
25
26 const LOGIN_ERRORS_TRANSIENT_KEY = 'tutor_login_errors';
27 /**
28 * Constructor
29 *
30 * @since 1.0.0
31 * @since 2.6.2 added allow_hooks param.
32 *
33 * @param bool $allow_hooks default value true.
34 *
35 * @return void
36 */
37 public function __construct( $allow_hooks = true ) {
38 if ( $allow_hooks ) {
39 add_action( 'wp_ajax_sync_video_playback', array( $this, 'sync_video_playback' ) );
40 add_action( 'wp_ajax_nopriv_sync_video_playback', array( $this, 'sync_video_playback_noprev' ) );
41 add_action( 'wp_ajax_tutor_place_rating', array( $this, 'tutor_place_rating' ) );
42 add_action( 'wp_ajax_delete_tutor_review', array( $this, 'delete_tutor_review' ) );
43
44 add_action( 'wp_ajax_tutor_course_add_to_wishlist', array( $this, 'tutor_course_add_to_wishlist' ) );
45 add_action( 'wp_ajax_nopriv_tutor_course_add_to_wishlist', array( $this, 'tutor_course_add_to_wishlist' ) );
46
47 /**
48 * Get all addons
49 */
50 add_action( 'wp_ajax_tutor_get_all_addons', array( $this, 'tutor_get_all_addons' ) );
51
52 /**
53 * Addon Enable Disable Control
54 */
55 add_action( 'wp_ajax_addon_enable_disable', array( $this, 'addon_enable_disable' ) );
56
57 /**
58 * Ajax login
59 *
60 * @since v.1.6.3
61 */
62 add_action( 'tutor_action_tutor_user_login', array( $this, 'process_tutor_login' ) );
63
64 /**
65 * Announcement
66 *
67 * @since v.1.7.9
68 */
69 add_action( 'wp_ajax_tutor_announcement_create', array( $this, 'create_or_update_annoucement' ) );
70 add_action( 'wp_ajax_tutor_announcement_delete', array( $this, 'delete_annoucement' ) );
71 }
72 }
73
74
75
76 /**
77 * Update video information and data when necessary
78 *
79 * @since 1.0.0
80 * @return void
81 */
82 public function sync_video_playback() {
83 tutor_utils()->checking_nonce();
84
85 $user_id = get_current_user_id();
86 $post_id = Input::post( 'post_id', 0, Input::TYPE_INT );
87 $duration = Input::post( 'duration' );
88 $current_time = Input::post( 'currentTime' );
89
90 if ( ! tutor_utils()->has_enrolled_content_access( 'lesson', $post_id ) ) {
91 wp_send_json_error( array( 'message' => __( 'Access Denied', 'tutor' ) ) );
92 exit;
93 }
94
95 /**
96 * Update posts attached video
97 */
98 $video = tutor_utils()->get_video( $post_id );
99
100 if ( $duration ) {
101 $video['duration_sec'] = $duration; // Duration in sec.
102 $video['playtime'] = tutor_utils()->playtime_string( $duration );
103 $video['runtime'] = tutor_utils()->playtime_array( $duration );
104 }
105 tutor_utils()->update_video( $post_id, $video );
106
107 /**
108 * Sync Lesson Reading Info by Users
109 */
110
111 $best_watch_time = tutor_utils()->get_lesson_reading_info( $post_id, $user_id, 'video_best_watched_time' );
112 if ( $best_watch_time < $current_time ) {
113 LessonModel::update_lesson_reading_info( $post_id, $user_id, 'video_best_watched_time', $current_time );
114 }
115
116 if ( Input::post( 'is_ended', false, Input::TYPE_BOOL ) ) {
117 LessonModel::mark_lesson_complete( $post_id );
118 }
119 exit();
120 }
121
122 /**
123 * Video playback callback for noprev
124 *
125 * @since 1.0.0
126 * @return void
127 */
128 public function sync_video_playback_noprev() {
129 }
130
131 /**
132 * Place rating
133 *
134 * @since 1.0.0
135 * @return void
136 */
137 public function tutor_place_rating() {
138 tutor_utils()->checking_nonce();
139
140 $user_id = get_current_user_id();
141 $course_id = Input::post( 'course_id' );
142 $rating = Input::post( 'tutor_rating_gen_input', 0, Input::TYPE_INT );
143 $review = Input::post( 'review', '', Input::TYPE_TEXTAREA );
144
145 $rating <= 0 ? $rating = 1 : 0;
146 $rating > 5 ? $rating = 5 : 0;
147
148 $this->add_or_update_review( $user_id, $course_id, $rating, $review );
149 }
150
151 /**
152 * Add/Update rating
153 *
154 * @param int $user_id the user id.
155 * @param int $course_id the course id.
156 * @param int $rating rating star number.
157 * @param string $review review description.
158 * @param int $review_id review id needed for api update.
159 *
160 * @return void|string
161 */
162 public function add_or_update_review( $user_id, $course_id, $rating, $review, $review_id = 0 ) {
163 global $wpdb;
164
165 $moderation = tutor_utils()->get_option( 'enable_course_review_moderation', false, true, true );
166 $user = get_userdata( $user_id );
167 $date = date( 'Y-m-d H:i:s', tutor_time() ); //phpcs:ignore
168
169 if ( ! tutor_is_rest() && ! tutor_utils()->has_enrolled_content_access( 'course', $course_id ) ) {
170 wp_send_json_error( array( 'message' => __( 'Access Denied', 'tutor' ) ) );
171 exit;
172 }
173
174 do_action( 'tutor_before_rating_placed' );
175
176 $is_edit = 0 === $review_id ? false : true;
177
178 if ( ! tutor_is_rest() ) {
179 $previous_rating_id = $wpdb->get_var(
180 $wpdb->prepare(
181 "SELECT comment_ID
182 from {$wpdb->comments}
183 WHERE comment_post_ID = %d AND
184 user_id = %d AND
185 comment_type = 'tutor_course_rating'
186 LIMIT 1;",
187 $course_id,
188 $user_id
189 )
190 );
191
192 if ( ! empty( $previous_rating_id ) ) {
193 $review_id = $previous_rating_id;
194 $is_edit = true;
195 }
196 }
197
198 if ( $is_edit ) {
199 $wpdb->update(
200 $wpdb->comments,
201 array(
202 'comment_content' => $review,
203 'comment_approved' => $moderation ? 'hold' : 'approved',
204 'comment_date' => $date,
205 'comment_date_gmt' => get_gmt_from_date( $date ),
206 ),
207 array( 'comment_ID' => $review_id )
208 );
209
210 $rating_info = $wpdb->get_row(
211 $wpdb->prepare(
212 "SELECT * FROM {$wpdb->commentmeta}
213 WHERE comment_id = %d
214 AND meta_key = 'tutor_rating'; ",
215 $review_id
216 )
217 );
218
219 if ( $rating_info ) {
220 $wpdb->update(
221 $wpdb->commentmeta,
222 array( 'meta_value' => $rating ),
223 array(
224 'comment_id' => $review_id,
225 'meta_key' => 'tutor_rating',
226 )
227 );
228 } else {
229 $wpdb->insert(
230 $wpdb->commentmeta,
231 array(
232 'comment_id' => $review_id,
233 'meta_key' => 'tutor_rating',
234 'meta_value' => $rating,
235 )
236 );
237 }
238 } else {
239 $data = array(
240 'comment_post_ID' => esc_sql( $course_id ),
241 'comment_approved' => $moderation ? 'hold' : 'approved',
242 'comment_type' => 'tutor_course_rating',
243 'comment_date' => $date,
244 'comment_date_gmt' => get_gmt_from_date( $date ),
245 'user_id' => $user_id,
246 'comment_author' => $user->user_login,
247 'comment_agent' => 'TutorLMSPlugin',
248 );
249 if ( $review ) {
250 $data['comment_content'] = $review;
251 }
252
253 $wpdb->insert( $wpdb->comments, $data );
254 $comment_id = (int) $wpdb->insert_id;
255 $review_id = $comment_id;
256
257 if ( $comment_id ) {
258 $result = $wpdb->insert(
259 $wpdb->commentmeta,
260 array(
261 'comment_id' => $comment_id,
262 'meta_key' => 'tutor_rating',
263 'meta_value' => $rating,
264 )
265 );
266
267 do_action( 'tutor_after_rating_placed', $comment_id );
268 }
269 }
270
271 if ( ! tutor_is_rest() ) {
272 wp_send_json_success(
273 array(
274 'message' => __( 'Rating placed successsully!', 'tutor' ),
275 'review_id' => $review_id,
276 )
277 );
278 } else {
279 return $is_edit ? 'updated' : 'created';
280 }
281 }
282
283 /**
284 * Delete a review
285 *
286 * @since 1.0.0
287 * @since 2.6.2 added params user_id.
288 * @param int $user_id the user id.
289 * @return void|bool
290 */
291 public function delete_tutor_review( $user_id = 0 ) {
292 if ( ! tutor_is_rest() ) {
293 tutor_utils()->checking_nonce();
294 }
295
296 $review_id = Input::post( 'review_id' );
297
298 if ( ! tutor_utils()->can_user_manage( 'review', $review_id, tutils()->get_user_id( $user_id ) ) ) {
299 wp_send_json_error( array( 'message' => __( 'Permissioned Denied!', 'tutor' ) ) );
300 exit;
301 }
302
303 global $wpdb;
304 $wpdb->delete( $wpdb->commentmeta, array( 'comment_id' => $review_id ) );
305 $wpdb->delete( $wpdb->comments, array( 'comment_ID' => $review_id ) );
306
307 if ( tutor_is_rest() ) {
308 return true;
309 }
310
311 wp_send_json_success();
312 }
313
314 /**
315 * Add course in wishlist
316 *
317 * @since 1.0.0
318 * @return void|string
319 */
320 public function tutor_course_add_to_wishlist() {
321 tutor_utils()->checking_nonce();
322
323 // Redirect login since only logged in user can add courses to wishlist.
324 if ( ! is_user_logged_in() ) {
325 wp_send_json_error(
326 array(
327 'redirect_to' => wp_login_url( wp_get_referer() ),
328 )
329 );
330 }
331
332 $user_id = get_current_user_id();
333 $course_id = Input::post( 'course_id', 0, Input::TYPE_INT );
334
335 $result = $this->add_or_delete_wishlist( $user_id, $course_id );
336
337 if ( tutor_is_rest() ) {
338 return $result;
339 } elseif ( 'added' === $result ) {
340 wp_send_json_success(
341 array(
342 'status' => 'added',
343 'message' => __( 'Course added to wish list', 'tutor' ),
344 )
345 );
346 } else {
347 wp_send_json_success(
348 array(
349 'status' => 'removed',
350 'message' => __( 'Course removed from wish list', 'tutor' ),
351 )
352 );
353 }
354 }
355
356 /**
357 * Add or Delete wishlist by user_id and course_id
358 *
359 * @since 2.6.2
360 *
361 * @param int $user_id the user id.
362 * @param int $course_id the course_id to add to the wishlist.
363 *
364 * @return string
365 */
366 public function add_or_delete_wishlist( $user_id, $course_id ) {
367 global $wpdb;
368
369 $if_added_to_list = tutor_utils()->is_wishlisted( $course_id, $user_id );
370
371 $result = '';
372
373 if ( $if_added_to_list ) {
374 $wpdb->delete(
375 $wpdb->usermeta,
376 array(
377 'user_id' => $user_id,
378 'meta_key' => '_tutor_course_wishlist',
379 'meta_value' => $course_id,
380 )
381 );
382
383 $result = 'removed';
384 } else {
385 add_user_meta( $user_id, '_tutor_course_wishlist', $course_id );
386
387 $result = 'added';
388 }
389
390 return $result;
391 }
392
393 /**
394 * Prepare addons data
395 *
396 * @since 1.0.0
397 * @return array
398 */
399 public function prepare_addons_data() {
400 $addons = apply_filters( 'tutor_addons_lists_config', array() );
401 $plugins_data = $addons;
402
403 if ( is_array( $addons ) && count( $addons ) ) {
404 foreach ( $addons as $base_name => $addon ) {
405 $addon_config = tutor_utils()->get_addon_config( $base_name );
406 $is_enabled = (bool) tutor_utils()->avalue_dot( 'is_enable', $addon_config );
407
408 $plugins_data[ $base_name ]['is_enabled'] = $is_enabled;
409
410 $thumbnail_url = tutor()->url . 'assets/images/tutor-plugin.png';
411 if ( file_exists( $addon['path'] . 'assets/images/thumbnail.png' ) ) {
412 $thumbnail_url = $addon['url'] . 'assets/images/thumbnail.png';
413 } elseif ( file_exists( $addon['path'] . 'assets/images/thumbnail.jpg' ) ) {
414 $thumbnail_url = $addon['url'] . 'assets/images/thumbnail.jpg';
415 } elseif ( file_exists( $addon['path'] . 'assets/images/thumbnail.svg' ) ) {
416 $thumbnail_url = $addon['url'] . 'assets/images/thumbnail.svg';
417 }
418
419 $plugins_data[ $base_name ]['thumb_url'] = $thumbnail_url;
420
421 /**
422 * Checking if there any dependant plugin exists
423 */
424 $depends = tutor_utils()->array_get( 'depend_plugins', $addon );
425 $plugins_required = array();
426 if ( tutor_utils()->count( $depends ) ) {
427 foreach ( $depends as $plugin_base => $plugin_name ) {
428 if ( ! is_plugin_active( $plugin_base ) ) {
429 $plugins_required[ $plugin_base ] = $plugin_name;
430 }
431 }
432 }
433
434 $depended_plugins = array();
435 foreach ( $plugins_required as $required_plugin ) {
436 array_push( $depended_plugins, $required_plugin );
437 }
438
439 $plugins_data[ $base_name ]['plugins_required'] = $depended_plugins;
440
441 // Check if it's notifications.
442 if ( function_exists( 'tutor_notifications' ) && tutor_notifications()->basename === $base_name ) {
443
444 $required = array();
445 version_compare( PHP_VERSION, '7.2.5', '>=' ) ? 0 : $required[] = __( 'PHP 7.2.5 or greater is required', 'tutor' );
446 ! is_ssl() ? $required[] = __( 'SSL certificate', 'tutor' ) : 0;
447
448 foreach ( array( 'curl', 'gmp', 'mbstring', 'openssl' ) as $ext ) {
449 ! extension_loaded( $ext ) ? $required[] = 'PHP extension <strong>' . $ext . '</strong>' : 0;
450 }
451
452 $plugins_data[ $base_name ]['ext_required'] = $required;
453 }
454 }
455 }
456
457 /**
458 * Keep same sorting order.
459 *
460 * @since 2.2.4
461 */
462 $free_addon_list = apply_filters( 'tutor_pro_addons_lists_for_display', array() );
463 $prepared_addons = array();
464
465 foreach ( $free_addon_list as $addon_name => $addon ) {
466 $key = "tutor-pro/addons/{$addon_name}/{$addon_name}.php";
467 if ( isset( $plugins_data[ $key ] ) ) {
468 $prepared_addons[] = $plugins_data[ $key ];
469 }
470 }
471
472 return $prepared_addons;
473 }
474
475 /**
476 * Get all notifications
477 *
478 * @since 1.0.0
479 * @return void
480 */
481 public function tutor_get_all_addons() {
482
483 // Check and verify the request.
484 tutor_utils()->checking_nonce();
485
486 if ( ! User::is_admin() ) {
487 wp_send_json_error( tutor_utils()->error_message() );
488 }
489
490 // All good, let's proceed.
491 $all_addons = $this->prepare_addons_data();
492
493 wp_send_json_success(
494 array(
495 'addons' => $all_addons,
496 )
497 );
498 }
499
500 /**
501 * Method for enable / disable addons
502 *
503 * @since 1.0.0
504 * @return void
505 */
506 public function addon_enable_disable() {
507
508 tutor_utils()->checking_nonce();
509
510 if ( ! current_user_can( 'manage_options' ) ) {
511 wp_send_json_error( array( 'message' => __( 'Access Denied', 'tutor' ) ) );
512 }
513
514 $form_data = json_decode( Input::post( 'addonFieldNames' ) );
515 $before_config = get_option( 'tutor_addons_config' );
516 $addons_config = array();
517
518 foreach ( $form_data as $addon_field_name => $is_enable ) {
519
520 $before_status = ! isset( $before_config[ $addon_field_name ] ) ? 0 : $before_config[ $addon_field_name ]['is_enable'];
521 $after_status = $is_enable ? 1 : 0;
522
523 if ( $before_status !== $after_status ) {
524 do_action( 'tutor_addon_before_enable_disable' );
525 if ( $is_enable ) {
526 do_action( "tutor_addon_before_enable_{$addon_field_name}" );
527 do_action( 'tutor_addon_before_enable', $addon_field_name );
528
529 $addons_config[ $addon_field_name ]['is_enable'] = 1;
530 update_option( 'tutor_addons_config', $addons_config );
531
532 do_action( 'tutor_addon_after_enable', $addon_field_name );
533 do_action( "tutor_addon_after_enable_{$addon_field_name}" );
534 } else {
535 do_action( "tutor_addon_before_disable_{$addon_field_name}" );
536 do_action( 'tutor_addon_before_disable', $addon_field_name );
537
538 $addons_config[ $addon_field_name ]['is_enable'] = 0;
539 update_option( 'tutor_addons_config', $addons_config );
540
541 do_action( 'tutor_addon_after_disable', $addon_field_name );
542 do_action( "tutor_addon_after_disable_{$addon_field_name}" );
543 }
544 do_action( 'tutor_addon_after_enable_disable' );
545 } else {
546 $addons_config[ $addon_field_name ]['is_enable'] = $after_status;
547 update_option( 'tutor_addons_config', $addons_config );
548 }
549 }
550
551 wp_send_json_success();
552 }
553
554 /**
555 * Process tutor login
556 *
557 * @since 1.6.3
558 *
559 * @since 2.1.3 Ajax removed, validation errors
560 * stores in session.
561 *
562 * @return void
563 */
564 public function process_tutor_login() {
565 $validation_error = new \WP_Error();
566
567 /**
568 * Separate nonce verification added to show nonce verification
569 * failed message in a proper way.
570 *
571 * @since 2.1.4
572 */
573 if ( ! wp_verify_nonce( $_POST[ tutor()->nonce ], tutor()->nonce_action ) ) { //phpcs:ignore
574 $validation_error->add( 401, __( 'Nonce verification failed', 'tutor' ) );
575 \set_transient( self::LOGIN_ERRORS_TRANSIENT_KEY, $validation_error->get_error_messages() );
576 return;
577 }
578 //phpcs:disable WordPress.Security.NonceVerification.Missing
579
580 /**
581 * No sanitization/wp_unslash needed for log & pwd since WordPress
582 * does itself
583 *
584 * @since 2.1.3
585 *
586 * @see https://developer.wordpress.org/reference/functions/wp_signon/
587 */
588 $username = tutor_utils()->array_get( 'log', $_POST ); //phpcs:ignore
589 $password = tutor_utils()->array_get( 'pwd', $_POST ); //phpcs:ignore
590 $redirect_to = isset( $_POST['redirect_to'] ) ? esc_url_raw( wp_unslash( $_POST['redirect_to'] ) ) : '';
591 $remember = isset( $_POST['rememberme'] );
592
593 try {
594 $creds = array(
595 'user_login' => trim( $username ),
596 'user_password' => $password,
597 'remember' => $remember,
598 );
599
600 $validation_error = apply_filters( 'tutor_process_login_errors', $validation_error, $creds['user_login'], $creds['user_password'] );
601
602 if ( $validation_error->get_error_code() ) {
603 $validation_error->add(
604 $validation_error->get_error_code(),
605 $validation_error->get_error_message()
606 );
607 }
608
609 if ( empty( $creds['user_login'] ) ) {
610 $validation_error->add(
611 400,
612 __( 'Username is required.', 'tutor' )
613 );
614 }
615
616 // On multi-site, ensure user exists on current site, if not add them before allowing login.
617 if ( is_multisite() ) {
618 $user_data = get_user_by( is_email( $creds['user_login'] ) ? 'email' : 'login', $creds['user_login'] );
619
620 if ( $user_data && ! is_user_member_of_blog( $user_data->ID, get_current_blog_id() ) ) {
621 add_user_to_blog( get_current_blog_id(), $user_data->ID, 'customer' );
622 }
623 }
624
625 // Perform the login.
626 $user = wp_signon( apply_filters( 'tutor_login_credentials', $creds ), is_ssl() );
627
628 if ( is_wp_error( $user ) ) {
629 // If no error exist then add WP login error, to prevent error duplication.
630 if ( ! $validation_error->has_errors() ) {
631 $validation_error->add( 400, $user->get_error_message() );
632 }
633 } else {
634 do_action( 'tutor_after_login_success', $user->ID );
635 // Since 1.9.8 do enroll if guest attempt to enroll.
636 $course_enroll_attempt = Input::post( 'tutor_course_enroll_attempt' );
637 if ( ! empty( $course_enroll_attempt ) && is_a( $user, 'WP_User' ) ) {
638 do_action( 'tutor_do_enroll_after_login_if_attempt', $course_enroll_attempt, $user->ID );
639 }
640 wp_safe_redirect( $redirect_to );
641 exit();
642 }
643 } catch ( \Exception $e ) {
644 do_action( 'tutor_login_failed' );
645 $validation_error->add( 400, $e->getMessage() );
646 } finally {
647 // Store errors in transient data.
648 \set_transient( self::LOGIN_ERRORS_TRANSIENT_KEY, $validation_error->get_error_messages() );
649 }
650 }
651
652 /**
653 * Create/Update announcement
654 *
655 * @since 1.7.9
656 * @return void
657 */
658 public function create_or_update_annoucement() {
659 tutor_utils()->checking_nonce();
660
661 $error = array();
662 $course_id = Input::post( 'tutor_announcement_course' );
663 $announcement_title = Input::post( 'tutor_announcement_title' );
664 $announcement_summary = Input::post( 'tutor_announcement_summary', '', Input::TYPE_TEXTAREA );
665
666 // Check if user can manage this announcment.
667 if ( ! tutor_utils()->can_user_manage( 'course', $course_id ) ) {
668 wp_send_json_error( array( 'message' => __( 'Access Denied', 'tutor' ) ) );
669 }
670
671 // Set data and sanitize it.
672 $form_data = array(
673 'post_type' => 'tutor_announcements',
674 'post_title' => $announcement_title,
675 'post_content' => $announcement_summary,
676 'post_parent' => $course_id,
677 'post_status' => 'publish',
678 );
679
680 if ( Input::has( 'announcement_id' ) ) {
681 $form_data['ID'] = Input::post( 'announcement_id' );
682 }
683
684 if ( ! empty( $form_data['ID'] ) ) {
685 if ( ! tutor_utils()->can_user_manage( 'announcement', $form_data['ID'] ) ) {
686 wp_send_json_error( array( 'message' => tutor_utils()->error_message() ) );
687 }
688 }
689
690 // Validation message set.
691 if ( empty( $form_data['post_parent'] ) ) {
692 $error['post_parent'] = __( 'Course name required', 'tutor' );
693
694 }
695
696 if ( empty( $form_data['post_title'] ) ) {
697 $error['post_title'] = __( 'Announcement title required', 'tutor' );
698 }
699
700 if ( empty( $form_data['post_content'] ) ) {
701 $error['post_content'] = __( 'Announcement summary required', 'tutor' );
702
703 }
704
705 if ( empty( $form_data['post_content'] ) ) {
706 $error['post_content'] = __( 'Announcement summary required', 'tutor' );
707
708 }
709
710 // If validation fails.
711 if ( count( $error ) > 0 ) {
712 wp_send_json_error(
713 array(
714 'message' => __( 'All fields required!', 'tutor' ),
715 'fields' => $error,
716 )
717 );
718 }
719
720 // Insert or update post.
721 $post_id = wp_insert_post( $form_data );
722 if ( $post_id > 0 ) {
723 $announcement = get_post( $post_id );
724 $action_type = Input::post( 'action_type' );
725
726 do_action( 'tutor_announcements/after/save', $post_id, $announcement, $action_type );
727
728 $resp_message = 'create' === $action_type ? __( 'Announcement created successfully', 'tutor' ) : __( 'Announcement updated successfully', 'tutor' );
729 wp_send_json_success( array( 'message' => $resp_message ) );
730 }
731
732 wp_send_json_error( array( 'message' => __( 'Something Went Wrong!', 'tutor' ) ) );
733 }
734
735 /**
736 * Delete announcement
737 *
738 * @since 1.7.9
739 * @return void
740 */
741 public function delete_annoucement() {
742 tutor_utils()->checking_nonce();
743
744 $announcement_id = Input::post( 'announcement_id' );
745
746 if ( ! tutor_utils()->can_user_manage( 'announcement', $announcement_id ) ) {
747 wp_send_json_error( array( 'message' => __( 'Access Denied', 'tutor' ) ) );
748 }
749
750 $delete = wp_delete_post( $announcement_id );
751 if ( $delete ) {
752 wp_send_json_success( array( 'message' => __( 'Announcement deleted successfully', 'tutor' ) ) );
753 }
754
755 wp_send_json_error( array( 'message' => __( 'Announcement delete failed', 'tutor' ) ) );
756 }
757 }
758