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