| @@ -1,110 +1,343 @@ | ||
| 1 | 1 | <?php |
| 2 | - | |
| 3 | 2 | /** |
| 4 | - * Class Instructor | |
| 5 | - * @package TUTOR | |
| 3 | + * Class Student | |
| 6 | 4 | * |
| 7 | - * @since v.1.0.0 | |
| 5 | + * @package Tutor\Student | |
| 6 | + * @author Themeum <support@themeum.com> | |
| 7 | + * @link https://themeum.com | |
| 8 | + * @since 1.0.0 | |
| 8 | 9 | */ |
| 9 | 10 | |
| 10 | 11 | namespace TUTOR; |
| 11 | 12 | |
| 13 | +if ( ! defined( 'ABSPATH' ) ) { | |
| 14 | + exit; | |
| 15 | +} | |
| 12 | 16 | |
| 17 | +/** | |
| 18 | + * Manage students | |
| 19 | + * | |
| 20 | + * @since 1.0.0 | |
| 21 | + */ | |
| 13 | 22 | class Student { |
| 14 | 23 | |
| 24 | + /** | |
| 25 | + * Bagged error messages | |
| 26 | + * | |
| 27 | + * @since 1.0.0 | |
| 28 | + * | |
| 29 | + * @var $error_msgs | |
| 30 | + */ | |
| 15 | 31 | protected $error_msgs = ''; |
| 32 | + | |
| 33 | + /** | |
| 34 | + * Handle Hooks | |
| 35 | + * | |
| 36 | + * @since 1.0.0 | |
| 37 | + */ | |
| 16 | 38 | public function __construct() { |
| 17 | - add_action('template_redirect', array($this, 'register_student')); | |
| 39 | + add_action( 'template_redirect', array( $this, 'register_student' ) ); | |
| 40 | + add_filter( 'get_avatar_url', array( $this, 'filter_avatar' ), 10, 3 ); | |
| 41 | + add_action( 'wp_ajax_tutor_social_profile', array( $this, 'tutor_social_profile' ) ); | |
| 42 | + add_action( 'wp_ajax_tutor_profile_password_reset', array( $this, 'tutor_reset_password' ) ); | |
| 43 | + add_action( 'wp_ajax_tutor_update_profile', array( $this, 'update_profile' ) ); | |
| 18 | 44 | } |
| 19 | 45 | |
| 20 | 46 | /** |
| 21 | 47 | * Register new user and mark him as student |
| 22 | 48 | * |
| 23 | - * @since v.1.0.0 | |
| 49 | + * @since 1.0.0 | |
| 50 | + * | |
| 51 | + * @return void | |
| 24 | 52 | */ |
| 25 | - public function register_student(){ | |
| 26 | - if ( ! isset($_POST['tutor_action']) || $_POST['tutor_action'] !== 'tutor_register_student' ){ | |
| 53 | + public function register_student() { | |
| 54 | + if ( 'tutor_register_student' !== Input::post( 'tutor_action', '' ) || ! get_option( 'users_can_register', false ) ) { | |
| 55 | + // Action must be register, and registration must be enabled in dashboard. | |
| 27 | 56 | return; |
| 28 | 57 | } |
| 29 | - //Checking nonce | |
| 58 | + | |
| 59 | + // Checking nonce. | |
| 30 | 60 | tutor_utils()->checking_nonce(); |
| 31 | 61 | |
| 32 | - $required_fields = apply_filters('tutor_student_registration_required_fields', array( | |
| 33 | - 'first_name' => __('First name field is required', 'tutor'), | |
| 34 | - 'last_name' => __('Last name field is required', 'tutor'), | |
| 35 | - 'email' => __('E-Mail field is required', 'tutor'), | |
| 36 | - 'user_login' => __('User Name field is required', 'tutor'), | |
| 37 | - 'phone_number' => __('Phone Number field is required', 'tutor'), | |
| 38 | - 'password' => __('Password field is required', 'tutor'), | |
| 39 | - 'password_confirmation' => __('Password Confirmation field is required', 'tutor'), | |
| 40 | - )); | |
| 62 | + $required_fields = apply_filters( | |
| 63 | + 'tutor_student_registration_required_fields', | |
| 64 | + array( | |
| 65 | + 'first_name' => __( 'First name field is required', 'tutor' ), | |
| 66 | + 'last_name' => __( 'Last name field is required', 'tutor' ), | |
| 67 | + 'email' => __( 'E-Mail field is required', 'tutor' ), | |
| 68 | + 'user_login' => __( 'User Name field is required', 'tutor' ), | |
| 69 | + 'password' => __( 'Password field is required', 'tutor' ), | |
| 70 | + 'password_confirmation' => __( 'Password Confirmation field is required', 'tutor' ), | |
| 71 | + ) | |
| 72 | + ); | |
| 41 | 73 | |
| 74 | + $terms_conditions_link = tutor_utils()->get_toc_page_link(); | |
| 75 | + if ( $terms_conditions_link ) { | |
| 76 | + $required_fields['terms_conditions'] = __( 'Please accept the Terms and Conditions to continue', 'tutor' ); | |
| 77 | + } | |
| 78 | + | |
| 42 | 79 | $validation_errors = array(); |
| 43 | - foreach ($required_fields as $required_key => $required_value){ | |
| 44 | - if (empty($_POST[$required_key])){ | |
| 45 | - $validation_errors[$required_key] = $required_value; | |
| 80 | + | |
| 81 | + // Registration error push into validation_errors. | |
| 82 | + $errors = apply_filters( 'registration_errors', new \WP_Error(), '', '' ); | |
| 83 | + foreach ( $errors->errors as $key => $value ) { | |
| 84 | + $validation_errors[ $key ] = $value[0]; | |
| 85 | + | |
| 86 | + } | |
| 87 | + | |
| 88 | + foreach ( $required_fields as $required_key => $required_value ) { | |
| 89 | + if ( empty( Input::post( $required_key, '' ) ) ) { | |
| 90 | + $validation_errors[ $required_key ] = $required_value; | |
| 46 | 91 | } |
| 47 | 92 | } |
| 48 | 93 | |
| 49 | - if (!filter_var(tutor_utils()->input_old('email'), FILTER_VALIDATE_EMAIL)) { | |
| 50 | - $validation_errors['email'] = __('Valid E-Mail is required', 'tutor'); | |
| 94 | + | |
| 95 | + if ( ! filter_var( tutor_utils()->input_old( 'email' ), FILTER_VALIDATE_EMAIL ) ) { | |
| 96 | + $validation_errors['email'] = __( 'Valid E-Mail is required', 'tutor' ); | |
| 51 | 97 | } |
| 52 | - if (tutor_utils()->input_old('password') !== tutor_utils()->input_old('password_confirmation')){ | |
| 53 | - $validation_errors['password_confirmation'] = __('Confirm password does not matched with Password field', 'tutor'); | |
| 98 | + if ( tutor_utils()->input_old( 'password' ) !== tutor_utils()->input_old( 'password_confirmation' ) ) { | |
| 99 | + $validation_errors['password_confirmation'] = __( 'Your passwords should match each other. Please recheck.', 'tutor' ); | |
| 54 | 100 | } |
| 55 | 101 | |
| 56 | - if (count($validation_errors)){ | |
| 102 | + if ( count( $validation_errors ) ) { | |
| 57 | 103 | $this->error_msgs = $validation_errors; |
| 58 | - add_filter('tutor_student_register_validation_errors', array($this, 'tutor_student_form_validation_errors')); | |
| 104 | + add_filter( 'tutor_student_register_validation_errors', array( $this, 'tutor_student_form_validation_errors' ) ); | |
| 59 | 105 | return; |
| 60 | 106 | } |
| 61 | 107 | |
| 62 | - $first_name = sanitize_text_field(tutor_utils()->input_old('first_name')); | |
| 63 | - $last_name = sanitize_text_field(tutor_utils()->input_old('last_name')); | |
| 64 | - $email = sanitize_text_field(tutor_utils()->input_old('email')); | |
| 65 | - $user_login = sanitize_text_field(tutor_utils()->input_old('user_login')); | |
| 66 | - $phone_number = sanitize_text_field(tutor_utils()->input_old('phone_number')); | |
| 67 | - $password = sanitize_text_field(tutor_utils()->input_old('password')); | |
| 68 | - $tutor_profile_bio = wp_kses_post(tutor_utils()->input_old('tutor_profile_bio')); | |
| 108 | + $first_name = sanitize_text_field( tutor_utils()->input_old( 'first_name' ) ); | |
| 109 | + $last_name = sanitize_text_field( tutor_utils()->input_old( 'last_name' ) ); | |
| 110 | + $email = sanitize_text_field( tutor_utils()->input_old( 'email' ) ); | |
| 111 | + $user_login = sanitize_text_field( tutor_utils()->input_old( 'user_login' ) ); | |
| 112 | + $password = sanitize_text_field( tutor_utils()->input_old( 'password' ) ); | |
| 69 | 113 | |
| 70 | 114 | $userdata = array( |
| 71 | - 'user_login' => $user_login, | |
| 72 | - 'user_email' => $email, | |
| 73 | - 'first_name' => $first_name, | |
| 74 | - 'last_name' => $last_name, | |
| 75 | - //'role' => tutor()->student_role, | |
| 76 | - 'user_pass' => $password, | |
| 115 | + 'user_login' => $user_login, | |
| 116 | + 'user_email' => $email, | |
| 117 | + 'first_name' => $first_name, | |
| 118 | + 'last_name' => $last_name, | |
| 119 | + 'user_pass' => $password, | |
| 77 | 120 | ); |
| 78 | 121 | |
| 79 | - $user_id = wp_insert_user( $userdata ) ; | |
| 80 | - if ( ! is_wp_error($user_id)){ | |
| 81 | - update_user_meta($user_id, 'phone_number', $phone_number); | |
| 82 | - update_user_meta($user_id, 'description', $tutor_profile_bio); | |
| 83 | - update_user_meta($user_id, '_tutor_profile_bio', $tutor_profile_bio); | |
| 122 | + global $wpdb; | |
| 123 | + $wpdb->query( 'START TRANSACTION' ); | |
| 84 | 124 | |
| 85 | - $user = get_user_by( 'id', $user_id ); | |
| 86 | - if( $user ) { | |
| 87 | - wp_set_current_user( $user_id, $user->user_login ); | |
| 88 | - wp_set_auth_cookie( $user_id ); | |
| 125 | + $user_id = wp_insert_user( $userdata ); | |
| 126 | + $enroll_attempt = Input::post( 'tutor_course_enroll_attempt', '' ); | |
| 127 | + | |
| 128 | + if ( is_wp_error( $user_id ) ) { | |
| 129 | + $this->error_msgs = $user_id->get_error_messages(); | |
| 130 | + add_filter( 'tutor_student_register_validation_errors', array( $this, 'tutor_student_form_validation_errors' ) ); | |
| 131 | + return; | |
| 132 | + } | |
| 133 | + | |
| 134 | + $user = get_user_by( 'id', $user_id ); | |
| 135 | + | |
| 136 | + $is_req_email_verification = apply_filters( 'tutor_require_email_verification', false ); | |
| 137 | + if ( $is_req_email_verification ) { | |
| 138 | + do_action( 'tutor_send_verification_mail', $user, $enroll_attempt ); | |
| 139 | + $reg_done = apply_filters( 'tutor_registration_done', true ); | |
| 140 | + if ( ! $reg_done ) { | |
| 141 | + $wpdb->query( 'ROLLBACK' ); | |
| 142 | + return; | |
| 143 | + } else { | |
| 144 | + $wpdb->query( 'COMMIT' ); | |
| 89 | 145 | } |
| 146 | + } else { | |
| 147 | + /** | |
| 148 | + * Tutor Free - reqular student reg process. | |
| 149 | + */ | |
| 150 | + $wpdb->query( 'COMMIT' ); | |
| 90 | 151 | |
| 91 | - $dashboard_url = tutor_utils()->tutor_dashboard_url(); | |
| 92 | - wp_redirect($dashboard_url); | |
| 152 | + wp_set_current_user( $user_id, $user->user_login ); | |
| 153 | + wp_set_auth_cookie( $user_id ); | |
| 154 | + | |
| 155 | + do_action( 'tutor_after_student_signup', $user_id ); | |
| 156 | + // since 1.9.8 do enroll if guest attempt to enroll. | |
| 157 | + if ( ! empty( $enroll_attempt ) ) { | |
| 158 | + do_action( 'tutor_do_enroll_after_login_if_attempt', $enroll_attempt, $user_id ); | |
| 159 | + } | |
| 160 | + | |
| 161 | + // Redirect page. | |
| 162 | + $redirect_page = tutor_utils()->array_get( 'redirect_to', $_REQUEST ); //phpcs:ignore | |
| 163 | + if ( ! $redirect_page ) { | |
| 164 | + $redirect_page = tutor_utils()->tutor_dashboard_url(); | |
| 165 | + } | |
| 166 | + wp_safe_redirect( apply_filters( 'tutor_student_register_redirect_url', $redirect_page, $user ) ); | |
| 93 | 167 | die(); |
| 94 | - }else{ | |
| 95 | - $this->error_msgs = $user_id->get_error_messages(); | |
| 96 | - add_filter('tutor_student_register_validation_errors', array($this, 'tutor_student_form_validation_errors')); | |
| 97 | - return; | |
| 98 | 168 | } |
| 99 | 169 | |
| 100 | 170 | $registration_page = tutor_utils()->student_register_url(); |
| 101 | - wp_redirect($registration_page); | |
| 171 | + wp_safe_redirect( $registration_page ); | |
| 102 | 172 | die(); |
| 103 | 173 | } |
| 104 | 174 | |
| 105 | - public function tutor_student_form_validation_errors(){ | |
| 175 | + /** | |
| 176 | + * Get validation error messages | |
| 177 | + * | |
| 178 | + * @since 1.0.0 | |
| 179 | + * | |
| 180 | + * @return mixed error messages | |
| 181 | + */ | |
| 182 | + public function tutor_student_form_validation_errors() { | |
| 106 | 183 | return $this->error_msgs; |
| 107 | 184 | } |
| 108 | - | |
| 109 | 185 | |
| 110 | -} | |
| 186 | + /** | |
| 187 | + * Update profile | |
| 188 | + * | |
| 189 | + * @since 1.0.0 | |
| 190 | + * | |
| 191 | + * @return void send wp_json response | |
| 192 | + */ | |
| 193 | + public function update_profile() { | |
| 194 | + // Checking nonce. | |
| 195 | + tutor_utils()->checking_nonce(); | |
| 196 | + | |
| 197 | + $user_id = get_current_user_id(); | |
| 198 | + do_action( 'tutor_profile_update_before', $user_id ); | |
| 199 | + | |
| 200 | + $first_name = sanitize_text_field( tutor_utils()->input_old( 'first_name' ) ); | |
| 201 | + $last_name = sanitize_text_field( tutor_utils()->input_old( 'last_name' ) ); | |
| 202 | + $phone_number = sanitize_text_field( tutor_utils()->input_old( 'phone_number' ) ); | |
| 203 | + $tutor_profile_bio = wp_kses( Input::post( 'tutor_profile_bio', '', Input::TYPE_KSES_POST ), tutor_utils()->allowed_profile_bio_tags() ); | |
| 204 | + $tutor_profile_job_title = sanitize_text_field( tutor_utils()->input_old( 'tutor_profile_job_title' ) ); | |
| 205 | + $timezone = Input::post( 'timezone', '' ); | |
| 206 | + | |
| 207 | + $display_name = sanitize_text_field( tutor_utils()->input_old( 'display_name' ) ); | |
| 208 | + | |
| 209 | + $userdata = array( | |
| 210 | + 'ID' => $user_id, | |
| 211 | + 'first_name' => $first_name, | |
| 212 | + 'last_name' => $last_name, | |
| 213 | + 'display_name' => $display_name, | |
| 214 | + ); | |
| 215 | + | |
| 216 | + $user_id = wp_update_user( $userdata ); | |
| 217 | + | |
| 218 | + if ( ! is_wp_error( $user_id ) ) { | |
| 219 | + update_user_meta( $user_id, User::PHONE_NUMBER_META, $phone_number ); | |
| 220 | + update_user_meta( $user_id, User::PROFILE_BIO_META, $tutor_profile_bio ); | |
| 221 | + update_user_meta( $user_id, User::PROFILE_JOB_TITLE_META, $tutor_profile_job_title ); | |
| 222 | + update_user_meta( $user_id, User::TIMEZONE_META, $timezone ); | |
| 223 | + } | |
| 224 | + | |
| 225 | + do_action( 'tutor_profile_update_after', $user_id ); | |
| 226 | + | |
| 227 | + wp_send_json_success( array( 'message' => __( 'Profile Updated', 'tutor' ) ) ); | |
| 228 | + } | |
| 229 | + | |
| 230 | + /** | |
| 231 | + * Filter Avatar, Change avatar URL with Tutor User Photo | |
| 232 | + * | |
| 233 | + * @since 1.0.0 | |
| 234 | + * | |
| 235 | + * @param string $url url. | |
| 236 | + * @param mixed $id_or_email id or email. | |
| 237 | + * @param array $args extra args. | |
| 238 | + * | |
| 239 | + * @return false|string | |
| 240 | + */ | |
| 241 | + public function filter_avatar( $url, $id_or_email, $args ) { | |
| 242 | + | |
| 243 | + $finder = false; | |
| 244 | + $is_id = is_numeric( $id_or_email ); | |
| 245 | + | |
| 246 | + if ( $is_id ) { | |
| 247 | + $finder = absint( $id_or_email ); | |
| 248 | + } elseif ( is_string( $id_or_email ) ) { | |
| 249 | + $finder = $id_or_email; | |
| 250 | + } elseif ( $id_or_email instanceof \WP_User ) { | |
| 251 | + // User Object. | |
| 252 | + $finder = $id_or_email->ID; | |
| 253 | + } elseif ( $id_or_email instanceof \WP_Post ) { | |
| 254 | + // Post Object. | |
| 255 | + $finder = (int) $id_or_email->post_author; | |
| 256 | + } elseif ( $id_or_email instanceof \WP_Comment ) { | |
| 257 | + return $url; | |
| 258 | + } | |
| 259 | + | |
| 260 | + if ( ! $finder ) { | |
| 261 | + return $url; | |
| 262 | + } | |
| 263 | + | |
| 264 | + $user = get_user_by( $is_id ? 'ID' : 'email', $finder ); | |
| 265 | + | |
| 266 | + if ( $user ) { | |
| 267 | + $profile_photo = get_user_meta( $user->ID, '_tutor_profile_photo', true ); | |
| 268 | + if ( $profile_photo ) { | |
| 269 | + $size = isset( $args['size'] ) ? $args['size'] : 'thumbnail'; | |
| 270 | + $url = wp_get_attachment_image_url( $profile_photo, $size ); | |
| 271 | + } | |
| 272 | + } | |
| 273 | + return $url; | |
| 274 | + } | |
| 275 | + | |
| 276 | + /** | |
| 277 | + * Password Rest | |
| 278 | + * | |
| 279 | + * @since 1.0.0 | |
| 280 | + * | |
| 281 | + * @return void send wp_json response | |
| 282 | + */ | |
| 283 | + public function tutor_reset_password() { | |
| 284 | + // Checking nonce. | |
| 285 | + tutor_utils()->checking_nonce(); | |
| 286 | + | |
| 287 | + $user = wp_get_current_user(); | |
| 288 | + | |
| 289 | + $previous_password = Input::post( 'previous_password', '' ); | |
| 290 | + $new_password = Input::post( 'new_password', '' ); | |
| 291 | + $confirm_new_password = Input::post( 'confirm_new_password', '' ); | |
| 292 | + | |
| 293 | + $previous_password_checked = wp_check_password( $previous_password, $user->user_pass, $user->ID ); | |
| 294 | + | |
| 295 | + $validation_errors = array(); | |
| 296 | + if ( ! $previous_password_checked ) { | |
| 297 | + $validation_errors['incorrect_previous_password'] = __( 'Incorrect Previous Password', 'tutor' ); | |
| 298 | + } | |
| 299 | + if ( empty( $new_password ) ) { | |
| 300 | + $validation_errors['new_password_required'] = __( 'New Password Required', 'tutor' ); | |
| 301 | + } | |
| 302 | + if ( empty( $confirm_new_password ) ) { | |
| 303 | + $validation_errors['confirm_password_required'] = __( 'Confirm Password Required', 'tutor' ); | |
| 304 | + } | |
| 305 | + if ( $new_password !== $confirm_new_password ) { | |
| 306 | + $validation_errors['password_not_matched'] = __( 'New password and confirm password does not matched', 'tutor' ); | |
| 307 | + } | |
| 308 | + | |
| 309 | + if ( $previous_password_checked && ! empty( $new_password ) && $new_password === $confirm_new_password ) { | |
| 310 | + wp_set_password( $new_password, $user->ID ); | |
| 311 | + wp_send_json_success( array( 'message' => __( 'Password Changed', 'tutor' ) ) ); | |
| 312 | + } | |
| 313 | + | |
| 314 | + $first_message = count( $validation_errors ) ? $validation_errors[ array_keys( $validation_errors )[0] ] : __( 'Something went wrong!', 'tutor' ); | |
| 315 | + wp_send_json_error( array( 'message' => $first_message ) ); | |
| 316 | + } | |
| 317 | + | |
| 318 | + /** | |
| 319 | + * Handle social links | |
| 320 | + * | |
| 321 | + * @since 2.0.0 | |
| 322 | + * | |
| 323 | + * @return void | |
| 324 | + */ | |
| 325 | + public function tutor_social_profile() { | |
| 326 | + tutor_utils()->checking_nonce(); | |
| 327 | + | |
| 328 | + $user_id = get_current_user_id(); | |
| 329 | + $tutor_user_social = tutor_utils()->tutor_user_social_icons(); | |
| 330 | + | |
| 331 | + foreach ( $tutor_user_social as $key => $social ) { | |
| 332 | + $user_social_value = sanitize_text_field( tutor_utils()->input_old( $key ) ); | |
| 333 | + if ( '' !== $user_social_value ) { | |
| 334 | + update_user_meta( $user_id, $key, $user_social_value ); | |
| 335 | + } else { | |
| 336 | + delete_user_meta( $user_id, $key ); | |
| 337 | + } | |
| 338 | + } | |
| 339 | + | |
| 340 | + wp_send_json_success( array( 'message' => __( 'Social Profile Updated', 'tutor' ) ) ); | |
| 341 | + die(); | |
| 342 | + } | |
| 343 | +} | |