PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 2.6.2
Tutor LMS – eLearning and online course solution v2.6.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 2 years ago Admin.php 2 years ago Ajax.php 2 years ago Announcements.php 3 years ago Assets.php 2 years ago Backend_Page_Trait.php 3 years ago Course.php 2 years ago Course_Embed.php 3 years ago Course_Filter.php 2 years ago Course_List.php 2 years 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 2 years ago Instructors_List.php 2 years ago Lesson.php 2 years ago Options_V2.php 2 years ago Permalink.php 2 years ago Post_types.php 2 years ago Private_Course_Access.php 3 years ago Q_and_A.php 2 years ago Question_Answers_List.php 3 years ago Quiz.php 2 years ago Quiz_Attempts_List.php 3 years ago RestAPI.php 2 years ago Reviews.php 3 years ago Rewrite_Rules.php 2 years ago Shortcode.php 2 years ago Student.php 2 years ago Students_List.php 3 years ago Taxonomies.php 3 years ago Template.php 3 years ago Theme_Compatibility.php 3 years ago Tools.php 3 years ago Tools_V2.php 3 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 2 years 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 2 years ago
Ajax.php
746 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 // All good, let's proceed.
487 $all_addons = $this->prepare_addons_data();
488
489 wp_send_json_success(
490 array(
491 'addons' => $all_addons,
492 )
493 );
494 }
495
496 /**
497 * Method for enable / disable addons
498 *
499 * @since 1.0.0
500 * @return void
501 */
502 public function addon_enable_disable() {
503
504 if ( ! current_user_can( 'manage_options' ) ) {
505 wp_send_json_error( array( 'message' => __( 'Access Denied', 'tutor' ) ) );
506 }
507
508 $form_data = json_decode( Input::post( 'addonFieldNames' ) );
509 $before_config = get_option( 'tutor_addons_config' );
510 $addons_config = array();
511
512 foreach ( $form_data as $addon_field_name => $is_enable ) {
513
514 $before_status = ! isset( $before_config[ $addon_field_name ] ) ? 0 : $before_config[ $addon_field_name ]['is_enable'];
515 $after_status = $is_enable ? 1 : 0;
516
517 if ( $before_status !== $after_status ) {
518 do_action( 'tutor_addon_before_enable_disable' );
519 if ( $is_enable ) {
520 do_action( "tutor_addon_before_enable_{$addon_field_name}" );
521 do_action( 'tutor_addon_before_enable', $addon_field_name );
522
523 $addons_config[ $addon_field_name ]['is_enable'] = 1;
524 update_option( 'tutor_addons_config', $addons_config );
525
526 do_action( 'tutor_addon_after_enable', $addon_field_name );
527 do_action( "tutor_addon_after_enable_{$addon_field_name}" );
528 } else {
529 do_action( "tutor_addon_before_disable_{$addon_field_name}" );
530 do_action( 'tutor_addon_before_disable', $addon_field_name );
531
532 $addons_config[ $addon_field_name ]['is_enable'] = 0;
533 update_option( 'tutor_addons_config', $addons_config );
534
535 do_action( 'tutor_addon_after_disable', $addon_field_name );
536 do_action( "tutor_addon_after_disable_{$addon_field_name}" );
537 }
538 do_action( 'tutor_addon_after_enable_disable' );
539 } else {
540 $addons_config[ $addon_field_name ]['is_enable'] = $after_status;
541 update_option( 'tutor_addons_config', $addons_config );
542 }
543 }
544
545 wp_send_json_success();
546 }
547
548 /**
549 * Process tutor login
550 *
551 * @since 1.6.3
552 *
553 * @since 2.1.3 Ajax removed, validation errors
554 * stores in session.
555 *
556 * @return void
557 */
558 public function process_tutor_login() {
559 $validation_error = new \WP_Error();
560
561 /**
562 * Separate nonce verification added to show nonce verification
563 * failed message in a proper way.
564 *
565 * @since 2.1.4
566 */
567 if ( ! wp_verify_nonce( $_POST[ tutor()->nonce ], tutor()->nonce_action ) ) { //phpcs:ignore
568 $validation_error->add( 401, __( 'Nonce verification failed', 'tutor' ) );
569 \set_transient( self::LOGIN_ERRORS_TRANSIENT_KEY, $validation_error->get_error_messages() );
570 return;
571 }
572 //phpcs:disable WordPress.Security.NonceVerification.Missing
573
574 /**
575 * No sanitization/wp_unslash needed for log & pwd since WordPress
576 * does itself
577 *
578 * @since 2.1.3
579 *
580 * @see https://developer.wordpress.org/reference/functions/wp_signon/
581 */
582 $username = tutor_utils()->array_get( 'log', $_POST ); //phpcs:ignore
583 $password = tutor_utils()->array_get( 'pwd', $_POST ); //phpcs:ignore
584 $redirect_to = isset( $_POST['redirect_to'] ) ? esc_url_raw( wp_unslash( $_POST['redirect_to'] ) ) : '';
585 $remember = isset( $_POST['rememberme'] );
586
587 try {
588 $creds = array(
589 'user_login' => trim( $username ),
590 'user_password' => $password,
591 'remember' => $remember,
592 );
593
594 $validation_error = apply_filters( 'tutor_process_login_errors', $validation_error, $creds['user_login'], $creds['user_password'] );
595
596 if ( $validation_error->get_error_code() ) {
597 $validation_error->add(
598 $validation_error->get_error_code(),
599 $validation_error->get_error_message()
600 );
601 }
602
603 if ( empty( $creds['user_login'] ) ) {
604 $validation_error->add(
605 400,
606 __( 'Username is required.', 'tutor' )
607 );
608 }
609
610 // On multi-site, ensure user exists on current site, if not add them before allowing login.
611 if ( is_multisite() ) {
612 $user_data = get_user_by( is_email( $creds['user_login'] ) ? 'email' : 'login', $creds['user_login'] );
613
614 if ( $user_data && ! is_user_member_of_blog( $user_data->ID, get_current_blog_id() ) ) {
615 add_user_to_blog( get_current_blog_id(), $user_data->ID, 'customer' );
616 }
617 }
618
619 // Perform the login.
620 $user = wp_signon( apply_filters( 'tutor_login_credentials', $creds ), is_ssl() );
621
622 if ( is_wp_error( $user ) ) {
623 // If no error exist then add WP login error, to prevent error duplication.
624 if ( ! $validation_error->has_errors() ) {
625 $validation_error->add( 400, $user->get_error_message() );
626 }
627 } else {
628 do_action( 'tutor_after_login_success', $user->ID );
629 // Since 1.9.8 do enroll if guest attempt to enroll.
630 $course_enroll_attempt = Input::post( 'tutor_course_enroll_attempt' );
631 if ( ! empty( $course_enroll_attempt ) && is_a( $user, 'WP_User' ) ) {
632 do_action( 'tutor_do_enroll_after_login_if_attempt', $course_enroll_attempt, $user->ID );
633 }
634 wp_safe_redirect( $redirect_to );
635 exit();
636 }
637 } catch ( \Exception $e ) {
638 do_action( 'tutor_login_failed' );
639 $validation_error->add( 400, $e->getMessage() );
640 } finally {
641 // Store errors in transient data.
642 \set_transient( self::LOGIN_ERRORS_TRANSIENT_KEY, $validation_error->get_error_messages() );
643 }
644 }
645
646 /**
647 * Create/Update announcement
648 *
649 * @since 1.7.9
650 * @return void
651 */
652 public function create_or_update_annoucement() {
653 tutor_utils()->checking_nonce();
654
655 $error = array();
656 $course_id = Input::post( 'tutor_announcement_course' );
657 $announcement_title = Input::post( 'tutor_announcement_title' );
658 $announcement_summary = Input::post( 'tutor_announcement_summary', '', Input::TYPE_TEXTAREA );
659
660 // Check if user can manage this announcment.
661 if ( ! tutor_utils()->can_user_manage( 'course', $course_id ) ) {
662 wp_send_json_error( array( 'message' => __( 'Access Denied', 'tutor' ) ) );
663 }
664
665 // Set data and sanitize it.
666 $form_data = array(
667 'post_type' => 'tutor_announcements',
668 'post_title' => $announcement_title,
669 'post_content' => $announcement_summary,
670 'post_parent' => $course_id,
671 'post_status' => 'publish',
672 );
673
674 if ( Input::has( 'announcement_id' ) ) {
675 $form_data['ID'] = Input::post( 'announcement_id' );
676 }
677
678 // Validation message set.
679 if ( empty( $form_data['post_parent'] ) ) {
680 $error['post_parent'] = __( 'Course name required', 'tutor' );
681
682 }
683
684 if ( empty( $form_data['post_title'] ) ) {
685 $error['post_title'] = __( 'Announcement title required', 'tutor' );
686 }
687
688 if ( empty( $form_data['post_content'] ) ) {
689 $error['post_content'] = __( 'Announcement summary required', 'tutor' );
690
691 }
692
693 if ( empty( $form_data['post_content'] ) ) {
694 $error['post_content'] = __( 'Announcement summary required', 'tutor' );
695
696 }
697
698 // If validation fails.
699 if ( count( $error ) > 0 ) {
700 wp_send_json_error(
701 array(
702 'message' => __( 'All fields required!', 'tutor' ),
703 'fields' => $error,
704 )
705 );
706 }
707
708 // Insert or update post.
709 $post_id = wp_insert_post( $form_data );
710 if ( $post_id > 0 ) {
711 $announcement = get_post( $post_id );
712 $action_type = Input::post( 'action_type' );
713
714 do_action( 'tutor_announcements/after/save', $post_id, $announcement, $action_type );
715
716 $resp_message = 'create' === $action_type ? __( 'Announcement created successfully', 'tutor' ) : __( 'Announcement updated successfully', 'tutor' );
717 wp_send_json_success( array( 'message' => $resp_message ) );
718 }
719
720 wp_send_json_error( array( 'message' => __( 'Something Went Wrong!', 'tutor' ) ) );
721 }
722
723 /**
724 * Delete announcement
725 *
726 * @since 1.7.9
727 * @return void
728 */
729 public function delete_annoucement() {
730 tutor_utils()->checking_nonce();
731
732 $announcement_id = Input::post( 'announcement_id' );
733
734 if ( ! tutor_utils()->can_user_manage( 'announcement', $announcement_id ) ) {
735 wp_send_json_error( array( 'message' => __( 'Access Denied', 'tutor' ) ) );
736 }
737
738 $delete = wp_delete_post( $announcement_id );
739 if ( $delete ) {
740 wp_send_json_success( array( 'message' => __( 'Announcement deleted successfully', 'tutor' ) ) );
741 }
742
743 wp_send_json_error( array( 'message' => __( 'Announcement delete failed', 'tutor' ) ) );
744 }
745 }
746