PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 4.0.3
Tutor LMS – eLearning and online course solution v4.0.3
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 / Student.php
tutor / classes Last commit date
Addons.php 4 weeks ago Admin.php 2 weeks ago Ajax.php 4 weeks ago Announcements.php 4 weeks ago Assets.php 3 weeks ago Backend_Page_Trait.php 1 year ago BaseController.php 1 year ago Config.php 4 weeks ago Container.php 1 year ago Course.php 4 weeks ago Course_Embed.php 3 years ago Course_Filter.php 4 weeks ago Course_List.php 4 weeks ago Course_Settings_Tabs.php 4 weeks ago Course_Widget.php 1 year ago Custom_Validation.php 4 weeks ago Dashboard.php 4 weeks ago Earnings.php 10 months ago FormHandler.php 4 weeks ago Frontend.php 4 weeks ago Gutenberg.php 1 year ago Icon.php 2 weeks ago Input.php 4 weeks ago Instructor.php 4 weeks ago Instructors_List.php 4 weeks ago Lesson.php 4 weeks ago Options_V2.php 4 weeks ago Permalink.php 4 weeks ago Post_types.php 4 weeks ago Private_Course_Access.php 4 weeks ago Q_And_A.php 4 weeks ago Question_Answers_List.php 1 year ago Quiz.php 2 weeks ago QuizBuilder.php 4 weeks ago Quiz_Attempts_List.php 3 weeks ago RestAPI.php 3 weeks ago Reviews.php 4 weeks ago Rewrite_Rules.php 2 years ago SampleCourse.php 4 weeks ago Shortcode.php 4 weeks ago Singleton.php 1 year ago Student.php 4 weeks ago Students_List.php 1 year ago Taxonomies.php 1 year ago Template.php 4 weeks ago Theme_Compatibility.php 3 years ago Tools.php 1 year ago Tools_V2.php 1 month ago Tutor.php 4 weeks ago TutorEDD.php 4 weeks ago Tutor_Base.php 2 years ago Tutor_Setup.php 4 weeks ago Upgrader.php 4 weeks ago User.php 2 weeks ago UserPreference.php 4 weeks ago Utils.php 2 weeks ago Video_Stream.php 3 years ago WhatsNew.php 3 weeks ago Withdraw.php 4 weeks ago Withdraw_Requests_List.php 1 year ago WooCommerce.php 4 weeks ago
Student.php
409 lines
1 <?php
2 /**
3 * Class Student
4 *
5 * @package Tutor\Student
6 * @author Themeum <support@themeum.com>
7 * @link https://themeum.com
8 * @since 1.0.0
9 */
10
11 namespace TUTOR;
12
13 use Tutor\GDPR\Controllers\LegalConsent;
14
15 if ( ! defined( 'ABSPATH' ) ) {
16 exit;
17 }
18
19 /**
20 * Manage students
21 *
22 * @since 1.0.0
23 */
24 class Student {
25
26 /**
27 * Bagged error messages
28 *
29 * @since 1.0.0
30 *
31 * @var $error_msgs
32 */
33 protected $error_msgs = '';
34
35 /**
36 * Handle Hooks
37 *
38 * @since 1.0.0
39 */
40 public function __construct() {
41 add_action( 'template_redirect', array( $this, 'register_student' ) );
42 add_filter( 'get_avatar_url', array( $this, 'filter_avatar' ), 10, 3 );
43 add_action( 'wp_ajax_tutor_social_profile', array( $this, 'tutor_social_profile' ) );
44 add_action( 'wp_ajax_tutor_profile_password_reset', array( $this, 'tutor_reset_password' ) );
45 add_action( 'wp_ajax_tutor_update_profile', array( $this, 'update_profile' ) );
46 }
47
48 /**
49 * Register new user and mark him as student
50 *
51 * @since 1.0.0
52 *
53 * @return void
54 */
55 public function register_student() {
56 if ( 'tutor_register_student' !== Input::post( 'tutor_action', '' ) || ! get_option( 'users_can_register', false ) ) {
57 // Action must be register, and registration must be enabled in dashboard.
58 return;
59 }
60
61 // Checking nonce.
62 tutor_utils()->checking_nonce();
63 $required_fields = apply_filters(
64 'tutor_student_registration_required_fields',
65 array(
66 'first_name' => __( 'First name field is required', 'tutor' ),
67 'last_name' => __( 'Last name field is required', 'tutor' ),
68 'email' => __( 'E-Mail field is required', 'tutor' ),
69 'user_login' => __( 'User Name field is required', 'tutor' ),
70 'password' => __( 'Password field is required', 'tutor' ),
71 'password_confirmation' => __( 'Password Confirmation field is required', 'tutor' ),
72 )
73 );
74
75 $validation_errors = array();
76
77 // Registration error push into validation_errors.
78 $errors = apply_filters( 'registration_errors', new \WP_Error(), '', '' );
79 foreach ( $errors->errors as $key => $value ) {
80 $validation_errors[ $key ] = $value[0];
81 }
82
83 foreach ( $required_fields as $required_key => $required_value ) {
84 if ( empty( Input::post( $required_key, '' ) ) ) {
85 $validation_errors[ $required_key ] = $required_value;
86 }
87 }
88
89 // @since 4.0.0 legal consent added.
90 $validate_consent = LegalConsent::validate_consent( LegalConsent::DISPLAY_ON_STD_REG, $_POST );
91 if ( is_wp_error( $validate_consent ) ) {
92 $validation_errors[ $validate_consent->get_error_code() ] = $validate_consent->get_error_message();
93 }
94
95 if ( ! filter_var( tutor_utils()->input_old( 'email' ), FILTER_VALIDATE_EMAIL ) ) {
96 $validation_errors['email'] = __( 'Valid E-Mail is required', 'tutor' );
97 }
98
99 if ( tutor_utils()->input_old( 'password' ) !== tutor_utils()->input_old( 'password_confirmation' ) ) {
100 $validation_errors['password_confirmation'] = __( 'Your passwords should match each other. Please recheck.', 'tutor' );
101 }
102
103 if ( count( $validation_errors ) ) {
104 $this->error_msgs = $validation_errors;
105 add_filter( 'tutor_student_register_validation_errors', array( $this, 'tutor_student_form_validation_errors' ) );
106 return;
107 }
108
109 $first_name = sanitize_text_field( tutor_utils()->input_old( 'first_name' ) );
110 $last_name = sanitize_text_field( tutor_utils()->input_old( 'last_name' ) );
111 $email = sanitize_text_field( tutor_utils()->input_old( 'email' ) );
112 $user_login = sanitize_text_field( tutor_utils()->input_old( 'user_login' ) );
113 $password = sanitize_text_field( tutor_utils()->input_old( 'password' ) );
114 $userdata = array(
115 'user_login' => $user_login,
116 'user_email' => $email,
117 'first_name' => $first_name,
118 'last_name' => $last_name,
119 'user_pass' => $password,
120 );
121
122 global $wpdb;
123 $wpdb->query( 'START TRANSACTION' );
124 $user_id = wp_insert_user( $userdata );
125 $enroll_attempt = Input::post( 'tutor_course_enroll_attempt', '' );
126 if ( is_wp_error( $user_id ) ) {
127 $this->error_msgs = $user_id->get_error_messages();
128 add_filter( 'tutor_student_register_validation_errors', array( $this, 'tutor_student_form_validation_errors' ) );
129 return;
130 }
131
132 $user = get_user_by( 'id', $user_id );
133
134 $redirect_url = '';
135
136 $is_req_email_verification = apply_filters( 'tutor_require_email_verification', false );
137 if ( $is_req_email_verification ) {
138 $redirect_url = tutor_utils()->student_register_url();
139
140 do_action( 'tutor_send_verification_mail', $user, $enroll_attempt );
141 $reg_done = apply_filters( 'tutor_registration_done', true );
142 if ( ! $reg_done ) {
143 $wpdb->query( 'ROLLBACK' );
144 return;
145 } else {
146 $wpdb->query( 'COMMIT' );
147
148 }
149 } else {
150 /**
151 * Tutor Free - reqular student reg process.
152 */
153 $wpdb->query( 'COMMIT' );
154
155 wp_set_current_user( $user_id, $user->user_login );
156 wp_set_auth_cookie( $user_id );
157 do_action( 'tutor_after_student_signup', $user_id );
158
159 // since 1.9.8 do enroll if guest attempt to enroll.
160 if ( ! empty( $enroll_attempt ) ) {
161 do_action( 'tutor_do_enroll_after_login_if_attempt', $enroll_attempt, $user_id );
162 }
163
164 // Redirect page.
165 $redirect_url = tutor_utils()->array_get( 'redirect_to', $_REQUEST ); //phpcs:ignore
166 if ( ! $redirect_url ) {
167 $redirect_url = tutor_utils()->tutor_dashboard_url();
168 }
169 }
170
171 do_action( 'tutor_new_user_registered', $user, $validate_consent );
172 wp_safe_redirect( apply_filters( 'tutor_student_register_redirect_url', tutor_utils()->get_nocache_url( $redirect_url ), $user ) );
173 die();
174 }
175
176 /**
177 * Get validation error messages
178 *
179 * @since 1.0.0
180 *
181 * @return mixed error messages
182 */
183 public function tutor_student_form_validation_errors() {
184 return $this->error_msgs;
185 }
186
187 /**
188 * Update profile
189 *
190 * @since 1.0.0
191 *
192 * @return void send wp_json response
193 */
194 public function update_profile() {
195 // Checking nonce.
196 tutor_utils()->checking_nonce();
197
198 $user_id = get_current_user_id();
199 do_action( 'tutor_profile_update_before', $user_id );
200
201 $first_name = sanitize_text_field( tutor_utils()->input_old( 'first_name' ) );
202 $last_name = sanitize_text_field( tutor_utils()->input_old( 'last_name' ) );
203 $phone_number = sanitize_text_field( tutor_utils()->input_old( 'phone_number' ) );
204 $tutor_profile_bio = wp_kses( Input::post( 'tutor_profile_bio', '', Input::TYPE_KSES_POST ), tutor_utils()->allowed_profile_bio_tags() );
205 $tutor_profile_job_title = sanitize_text_field( tutor_utils()->input_old( 'tutor_profile_job_title' ) );
206 $timezone = Input::post( 'timezone', '' );
207
208 $display_name = sanitize_text_field( tutor_utils()->input_old( 'display_name' ) );
209
210 $userdata = array(
211 'ID' => $user_id,
212 'first_name' => $first_name,
213 'last_name' => $last_name,
214 'display_name' => $display_name,
215 );
216
217 $user_id = wp_update_user( $userdata );
218
219 if ( ! is_wp_error( $user_id ) ) {
220 update_user_meta( $user_id, User::PHONE_NUMBER_META, $phone_number );
221 update_user_meta( $user_id, User::PROFILE_BIO_META, $tutor_profile_bio );
222 update_user_meta( $user_id, User::PROFILE_JOB_TITLE_META, $tutor_profile_job_title );
223 update_user_meta( $user_id, User::TIMEZONE_META, $timezone );
224 }
225
226 do_action( 'tutor_profile_update_after', $user_id );
227
228 wp_send_json_success( array( 'message' => __( 'Profile Updated', 'tutor' ) ) );
229 }
230
231 /**
232 * Filter Avatar, Change avatar URL with Tutor User Photo
233 *
234 * @since 1.0.0
235 *
236 * @param string $url url.
237 * @param mixed $id_or_email id or email.
238 * @param array $args extra args.
239 *
240 * @return false|string
241 */
242 public function filter_avatar( $url, $id_or_email, $args ) {
243
244 $finder = false;
245 $is_id = is_numeric( $id_or_email );
246
247 if ( $is_id ) {
248 $finder = absint( $id_or_email );
249 } elseif ( is_string( $id_or_email ) ) {
250 $finder = $id_or_email;
251 } elseif ( $id_or_email instanceof \WP_User ) {
252 // User Object.
253 $finder = $id_or_email->ID;
254 } elseif ( $id_or_email instanceof \WP_Post ) {
255 // Post Object.
256 $finder = (int) $id_or_email->post_author;
257 } elseif ( $id_or_email instanceof \WP_Comment ) {
258 return $url;
259 }
260
261 if ( ! $finder ) {
262 return $url;
263 }
264
265 $user = get_user_by( $is_id ? 'ID' : 'email', $finder );
266
267 if ( $user ) {
268 $profile_photo = get_user_meta( $user->ID, '_tutor_profile_photo', true );
269 if ( $profile_photo ) {
270 $size = isset( $args['size'] ) ? $args['size'] : 'thumbnail';
271 $url = wp_get_attachment_image_url( $profile_photo, $size );
272 }
273 }
274 return $url;
275 }
276
277 /**
278 * Password Rest
279 *
280 * @since 1.0.0
281 *
282 * @return void send wp_json response
283 */
284 public function tutor_reset_password() {
285 // Checking nonce.
286 tutor_utils()->checking_nonce();
287
288 $user = wp_get_current_user();
289
290 $previous_password = Input::post( 'previous_password', '' );
291 $new_password = Input::post( 'new_password', '' );
292 $confirm_new_password = Input::post( 'confirm_new_password', '' );
293
294 $previous_password_checked = wp_check_password( $previous_password, $user->user_pass, $user->ID );
295
296 $validation_errors = array();
297 if ( ! $previous_password_checked ) {
298 $validation_errors['incorrect_previous_password'] = __( 'Incorrect Previous Password', 'tutor' );
299 }
300 if ( empty( $new_password ) ) {
301 $validation_errors['new_password_required'] = __( 'New Password Required', 'tutor' );
302 }
303 if ( empty( $confirm_new_password ) ) {
304 $validation_errors['confirm_password_required'] = __( 'Confirm Password Required', 'tutor' );
305 }
306 if ( $new_password !== $confirm_new_password ) {
307 $validation_errors['password_not_matched'] = __( 'New password and confirm password does not matched', 'tutor' );
308 }
309
310 if ( $previous_password_checked && ! empty( $new_password ) && $new_password === $confirm_new_password ) {
311 wp_set_password( $new_password, $user->ID );
312 wp_send_json_success( array( 'message' => __( 'Password Changed', 'tutor' ) ) );
313 }
314
315 $first_message = count( $validation_errors ) ? $validation_errors[ array_keys( $validation_errors )[0] ] : __( 'Something went wrong!', 'tutor' );
316 wp_send_json_error( array( 'message' => $first_message ) );
317 }
318
319 /**
320 * Handle social links
321 *
322 * @since 2.0.0
323 *
324 * @return void
325 */
326 public function tutor_social_profile() {
327 tutor_utils()->checking_nonce();
328
329 $user_id = get_current_user_id();
330 $tutor_user_social = tutor_utils()->tutor_user_social_icons();
331
332 foreach ( $tutor_user_social as $key => $social ) {
333 $user_social_value = sanitize_text_field( tutor_utils()->input_old( $key ) );
334 if ( '' !== $user_social_value ) {
335 update_user_meta( $user_id, $key, $user_social_value );
336 } else {
337 delete_user_meta( $user_id, $key );
338 }
339 }
340
341 wp_send_json_success( array( 'message' => __( 'Social Profile Updated', 'tutor' ) ) );
342 die();
343 }
344
345 /**
346 * Get courses tab configuration for student dashboard
347 *
348 * Generates the tab structure for displaying student courses with dropdown options
349 * for enrolled, active, and completed courses including counts and navigation URLs.
350 *
351 * @since 4.0.0
352 *
353 * @param string $active_tab The currently active tab identifier.
354 * @param array $post_type_args Query arguments for post type filtering.
355 * @param int $enrolled_course_count Number of enrolled courses.
356 * @param int $active_course_count Number of active courses.
357 * @param int $completed_course_count Number of completed courses.
358 *
359 * @return array Array containing tab configuration with dropdown options
360 */
361 public function get_courses_tab( $active_tab, $post_type_args, $enrolled_course_count, $active_course_count, $completed_course_count ) {
362 $courses_tab = array(
363 array(
364 'type' => 'dropdown',
365 'active' => ( ( 'courses' === $active_tab ) || ( 'courses/active-courses' === $active_tab ) || ( 'courses/completed-courses' === $active_tab ) ) ? true : false,
366 'options' => array(
367 array(
368 'label' => __( 'Enrolled', 'tutor' ),
369 'icon' => Icon::ENROLLED,
370 'url' => esc_url( add_query_arg( $post_type_args, tutor_utils()->get_tutor_dashboard_page_permalink( 'courses' ) ) ),
371 'active' => 'courses' === $active_tab ? true : false,
372 'count' => $enrolled_course_count,
373 ),
374 array(
375 'label' => __( 'Active', 'tutor' ),
376 'icon' => Icon::PLAY_LINE_2,
377 'url' => esc_url( add_query_arg( $post_type_args, tutor_utils()->get_tutor_dashboard_page_permalink( 'courses/active-courses' ) ) ),
378 'active' => 'courses/active-courses' === $active_tab ? true : false,
379 'count' => $active_course_count,
380 ),
381 array(
382 'label' => __( 'Complete', 'tutor' ),
383 'icon' => Icon::COMPLETED_CIRCLE,
384 'url' => esc_url( add_query_arg( $post_type_args, tutor_utils()->get_tutor_dashboard_page_permalink( 'courses/completed-courses' ) ) ),
385 'active' => 'courses/completed-courses' === $active_tab ? true : false,
386 'count' => $completed_course_count,
387 ),
388 ),
389 ),
390 array(
391 'type' => 'link',
392 'label' => __( 'Wishlist', 'tutor' ),
393 'icon' => Icon::WISHLIST,
394 'url' => esc_url( tutor_utils()->tutor_dashboard_url( 'courses/wishlist' ) ),
395 'active' => 'courses/wishlist' === $active_tab ? true : false,
396 ),
397 array(
398 'type' => 'link',
399 'label' => __( 'Quiz Attempts', 'tutor' ),
400 'icon' => Icon::QUIZ_2,
401 'url' => esc_url( tutor_utils()->tutor_dashboard_url( 'courses/my-quiz-attempts' ) ),
402 'active' => 'courses/my-quiz-attempts' === $active_tab ? true : false,
403 ),
404 );
405
406 return $courses_tab;
407 }
408 }
409